mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 10:16:07 +00:00
Refactor the support for AffineMap and IntegerSet aliases in the parser into more general support for attribute aliases.
`#` alias `=` attribute-value This also allows for dialects to define aliases for attributes in the AsmPrinter. The printer supports two types of attribute aliases, 'direct' and 'kind'. * Direct aliases are synonymous with the current support for type aliases, i.e. this maps an alias to a specific instance of an attribute. // A direct alias ("foo_str") for the string attribute "foo". #foo_str = "foo" * Kind aliases generates unique names for all instances of a given attribute kind. The generated aliases are of the form: `alias[0-9]+`. // A kind alias ("strattr") for all string attributes could generate. #strattr0 = "foo" #strattr1 = "bar" ... #strattrN = "baz" -- PiperOrigin-RevId: 246851916
This commit is contained in:
parent
3df7a80265
commit
94afc426e2
@ -95,15 +95,18 @@ public:
|
||||
/// Registered hooks for getting identifier aliases for symbols. The
|
||||
/// identifier is used in place of the symbol when printing textual IR.
|
||||
///
|
||||
/// Hook for defining AffineMap aliases.
|
||||
virtual void getAffineMapAliases(
|
||||
SmallVectorImpl<std::pair<StringRef, AffineMap>> &aliases) {}
|
||||
/// Hook for defining IntegerSet aliases.
|
||||
virtual void getIntegerSetAliases(
|
||||
SmallVectorImpl<std::pair<StringRef, IntegerSet>> &aliases) {}
|
||||
/// Hook for defining Attribute kind aliases. This will generate an alias for
|
||||
/// all attributes of the given kind in the form : <alias>[0-9]+. These
|
||||
/// aliases must not contain `.`.
|
||||
virtual void getAttributeKindAliases(
|
||||
SmallVectorImpl<std::pair<unsigned, StringRef>> &aliases) {}
|
||||
/// Hook for defining Attribute aliases. These aliases must not contain `.` or
|
||||
/// end with a numeric digit([0-9]+).
|
||||
virtual void getAttributeAliases(
|
||||
SmallVectorImpl<std::pair<Attribute, StringRef>> &aliases) {}
|
||||
/// Hook for defining Type aliases.
|
||||
virtual void
|
||||
getTypeAliases(SmallVectorImpl<std::pair<StringRef, Type>> &aliases) {}
|
||||
getTypeAliases(SmallVectorImpl<std::pair<Type, StringRef>> &aliases) {}
|
||||
|
||||
/// Verify an attribute from this dialect on the given function. Returns
|
||||
/// failure if the verification failed, success otherwise.
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "mlir/Support/STLExtras.h"
|
||||
#include "llvm/ADT/APFloat.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/MapVector.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
@ -79,6 +80,9 @@ static llvm::cl::opt<bool>
|
||||
|
||||
namespace {
|
||||
class ModuleState {
|
||||
/// A special index constant used for non-kind attribute aliases.
|
||||
static constexpr int kNonAttrKindAlias = -1;
|
||||
|
||||
public:
|
||||
/// This is the current context if it is knowable, otherwise this is null.
|
||||
MLIRContext *const context;
|
||||
@ -88,51 +92,68 @@ public:
|
||||
// Initializes module state, populating affine map state.
|
||||
void initialize(Module *module);
|
||||
|
||||
StringRef getAffineMapAlias(AffineMap affineMap) const {
|
||||
return affineMapToAlias.lookup(affineMap);
|
||||
Twine getAttributeAlias(Attribute attr) const {
|
||||
auto alias = attrToAlias.find(attr);
|
||||
if (alias == attrToAlias.end())
|
||||
return Twine();
|
||||
|
||||
// Return the alias for this attribute, along with the index if this was
|
||||
// generated by a kind alias.
|
||||
int kindIndex = alias->second.second;
|
||||
return alias->second.first +
|
||||
(kindIndex == kNonAttrKindAlias ? Twine() : Twine(kindIndex));
|
||||
}
|
||||
|
||||
int getAffineMapId(AffineMap affineMap) const {
|
||||
auto it = affineMapIds.find(affineMap);
|
||||
if (it == affineMapIds.end()) {
|
||||
return -1;
|
||||
void printAttributeAliases(raw_ostream &os) const {
|
||||
auto printAlias = [&](StringRef alias, Attribute attr, int index) {
|
||||
os << '#' << alias;
|
||||
if (index != kNonAttrKindAlias)
|
||||
os << index;
|
||||
os << " = " << attr << '\n';
|
||||
};
|
||||
|
||||
// Print all of the attribute kind aliases.
|
||||
for (auto &kindAlias : attrKindToAlias) {
|
||||
for (unsigned i = 0, e = kindAlias.second.second.size(); i != e; ++i)
|
||||
printAlias(kindAlias.second.first, kindAlias.second.second[i], i);
|
||||
os << "\n";
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
ArrayRef<AffineMap> getAffineMapIds() const { return affineMapsById; }
|
||||
|
||||
StringRef getIntegerSetAlias(IntegerSet integerSet) const {
|
||||
return integerSetToAlias.lookup(integerSet);
|
||||
}
|
||||
|
||||
int getIntegerSetId(IntegerSet integerSet) const {
|
||||
auto it = integerSetIds.find(integerSet);
|
||||
if (it == integerSetIds.end()) {
|
||||
return -1;
|
||||
// In a second pass print all of the remaining attribute aliases that aren't
|
||||
// kind aliases.
|
||||
for (Attribute attr : usedAttributes) {
|
||||
auto alias = attrToAlias.find(attr);
|
||||
if (alias != attrToAlias.end() &&
|
||||
alias->second.second == kNonAttrKindAlias)
|
||||
printAlias(alias->second.first, attr, alias->second.second);
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
ArrayRef<IntegerSet> getIntegerSetIds() const { return integerSetsById; }
|
||||
|
||||
StringRef getTypeAlias(Type ty) const { return typeToAlias.lookup(ty); }
|
||||
|
||||
ArrayRef<Type> getTypeIds() const { return usedTypes.getArrayRef(); }
|
||||
|
||||
private:
|
||||
void recordAffineMapReference(AffineMap affineMap) {
|
||||
if (affineMapIds.count(affineMap) == 0) {
|
||||
affineMapIds[affineMap] = affineMapsById.size();
|
||||
affineMapsById.push_back(affineMap);
|
||||
void printTypeAliases(raw_ostream &os) const {
|
||||
for (Type type : usedTypes) {
|
||||
auto alias = typeToAlias.find(type);
|
||||
if (alias != typeToAlias.end())
|
||||
os << '!' << alias->second << " = type " << type << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
void recordIntegerSetReference(IntegerSet integerSet) {
|
||||
if (integerSetIds.count(integerSet) == 0) {
|
||||
integerSetIds[integerSet] = integerSetsById.size();
|
||||
integerSetsById.push_back(integerSet);
|
||||
}
|
||||
private:
|
||||
void recordAttributeReference(Attribute attr) {
|
||||
// Don't recheck attributes that have already been seen or those that
|
||||
// already have an alias.
|
||||
if (!usedAttributes.insert(attr) || attrToAlias.count(attr))
|
||||
return;
|
||||
|
||||
// If this attribute kind has an alias, then record one for this attribute.
|
||||
auto alias = attrKindToAlias.find(static_cast<unsigned>(attr.getKind()));
|
||||
if (alias == attrKindToAlias.end())
|
||||
return;
|
||||
std::pair<StringRef, int> attrAlias(alias->second.first,
|
||||
alias->second.second.size());
|
||||
attrToAlias.insert({attr, attrAlias});
|
||||
alias->second.second.push_back(attr);
|
||||
}
|
||||
|
||||
void recordTypeReference(Type ty) { usedTypes.insert(ty); }
|
||||
@ -145,15 +166,23 @@ private:
|
||||
// Initialize symbol aliases.
|
||||
void initializeSymbolAliases();
|
||||
|
||||
DenseMap<AffineMap, int> affineMapIds;
|
||||
std::vector<AffineMap> affineMapsById;
|
||||
DenseMap<AffineMap, StringRef> affineMapToAlias;
|
||||
/// Set of attributes known to be used within the module.
|
||||
llvm::SetVector<Attribute> usedAttributes;
|
||||
|
||||
DenseMap<IntegerSet, int> integerSetIds;
|
||||
std::vector<IntegerSet> integerSetsById;
|
||||
DenseMap<IntegerSet, StringRef> integerSetToAlias;
|
||||
/// Mapping between attribute and a pair comprised of a base alias name and a
|
||||
/// count suffix. If the suffix is set to -1, it is not displayed.
|
||||
llvm::MapVector<Attribute, std::pair<StringRef, int>> attrToAlias;
|
||||
|
||||
/// Mapping between attribute kind and a pair comprised of a base alias name
|
||||
/// and a unique list of attributes belonging to this kind sorted by location
|
||||
/// seen in the module.
|
||||
llvm::MapVector<unsigned, std::pair<StringRef, std::vector<Attribute>>>
|
||||
attrKindToAlias;
|
||||
|
||||
/// Set of types known to be used within the module.
|
||||
llvm::SetVector<Type> usedTypes;
|
||||
|
||||
/// A mapping between a type and a given alias.
|
||||
DenseMap<Type, StringRef> typeToAlias;
|
||||
};
|
||||
} // end anonymous namespace
|
||||
@ -169,24 +198,18 @@ void ModuleState::visitType(Type type) {
|
||||
visitType(result);
|
||||
} else if (auto memref = type.dyn_cast<MemRefType>()) {
|
||||
// Visit affine maps in memref type.
|
||||
for (auto map : memref.getAffineMaps()) {
|
||||
recordAffineMapReference(map);
|
||||
}
|
||||
for (auto map : memref.getAffineMaps())
|
||||
recordAttributeReference(AffineMapAttr::get(map));
|
||||
} else if (auto vecOrTensor = type.dyn_cast<VectorOrTensorType>()) {
|
||||
visitType(vecOrTensor.getElementType());
|
||||
}
|
||||
}
|
||||
|
||||
void ModuleState::visitAttribute(Attribute attr) {
|
||||
if (auto mapAttr = attr.dyn_cast<AffineMapAttr>()) {
|
||||
recordAffineMapReference(mapAttr.getValue());
|
||||
} else if (auto setAttr = attr.dyn_cast<IntegerSetAttr>()) {
|
||||
recordIntegerSetReference(setAttr.getValue());
|
||||
} else if (auto arrayAttr = attr.dyn_cast<ArrayAttr>()) {
|
||||
for (auto elt : arrayAttr.getValue()) {
|
||||
recordAttributeReference(attr);
|
||||
if (auto arrayAttr = attr.dyn_cast<ArrayAttr>())
|
||||
for (auto elt : arrayAttr.getValue())
|
||||
visitAttribute(elt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModuleState::visitOperation(Operation *op) {
|
||||
@ -202,21 +225,14 @@ void ModuleState::visitOperation(Operation *op) {
|
||||
}
|
||||
|
||||
// Utility to generate a function to register a symbol alias.
|
||||
template <typename SymbolsInModuleSetTy, typename SymbolTy>
|
||||
static void registerSymbolAlias(StringRef name, SymbolTy sym,
|
||||
SymbolsInModuleSetTy &symbolsInModuleSet,
|
||||
llvm::StringSet<> &usedAliases,
|
||||
DenseMap<SymbolTy, StringRef> &symToAlias) {
|
||||
static bool canRegisterAlias(StringRef name, llvm::StringSet<> &usedAliases) {
|
||||
assert(!name.empty() && "expected alias name to be non-empty");
|
||||
assert(sym && "expected alias symbol to be non-null");
|
||||
// TODO(riverriddle) Assert that the provided alias name can be lexed as
|
||||
// an identifier.
|
||||
|
||||
// Check if the symbol is not referenced by the module or the name is
|
||||
// already used by another alias.
|
||||
if (!symbolsInModuleSet.count(sym) || !usedAliases.insert(name).second)
|
||||
return;
|
||||
symToAlias.try_emplace(sym, name);
|
||||
// Check that the alias doesn't contain a '.' character and the name is not
|
||||
// already in use.
|
||||
return !name.contains('.') && usedAliases.insert(name).second;
|
||||
}
|
||||
|
||||
void ModuleState::initializeSymbolAliases() {
|
||||
@ -228,53 +244,76 @@ void ModuleState::initializeSymbolAliases() {
|
||||
auto dialects = context->getRegisteredDialects();
|
||||
|
||||
// Collect the set of aliases from each dialect.
|
||||
SmallVector<std::pair<StringRef, AffineMap>, 8> affineMapAliases;
|
||||
SmallVector<std::pair<StringRef, IntegerSet>, 8> integerSetAliases;
|
||||
SmallVector<std::pair<StringRef, Type>, 16> typeAliases;
|
||||
SmallVector<std::pair<unsigned, StringRef>, 8> attributeKindAliases;
|
||||
SmallVector<std::pair<Attribute, StringRef>, 8> attributeAliases;
|
||||
SmallVector<std::pair<Type, StringRef>, 16> typeAliases;
|
||||
|
||||
// AffineMap/Integer set have specific kind aliases.
|
||||
attributeKindAliases.emplace_back(
|
||||
static_cast<unsigned>(Attribute::Kind::AffineMap), "map");
|
||||
attributeKindAliases.emplace_back(
|
||||
static_cast<unsigned>(Attribute::Kind::IntegerSet), "set");
|
||||
|
||||
for (auto *dialect : dialects) {
|
||||
dialect->getAffineMapAliases(affineMapAliases);
|
||||
dialect->getIntegerSetAliases(integerSetAliases);
|
||||
dialect->getAttributeKindAliases(attributeKindAliases);
|
||||
dialect->getAttributeAliases(attributeAliases);
|
||||
dialect->getTypeAliases(typeAliases);
|
||||
}
|
||||
|
||||
// Register the affine aliases.
|
||||
// Create a regex for the non-alias names of sets and maps, so that an alias
|
||||
// is not registered with a conflicting name.
|
||||
llvm::Regex reservedAffineNames("(set|map)[0-9]+");
|
||||
|
||||
// AffineMap aliases
|
||||
for (auto &affineAliasPair : affineMapAliases) {
|
||||
if (!reservedAffineNames.match(affineAliasPair.first))
|
||||
registerSymbolAlias(affineAliasPair.first, affineAliasPair.second,
|
||||
affineMapIds, usedAliases, affineMapToAlias);
|
||||
// Setup the attribute kind aliases.
|
||||
StringRef alias;
|
||||
unsigned attrKind;
|
||||
for (auto &attrAliasPair : attributeKindAliases) {
|
||||
std::tie(attrKind, alias) = attrAliasPair;
|
||||
assert(!alias.empty() && "expected non-empty alias string");
|
||||
if (!usedAliases.count(alias) && !alias.contains('.'))
|
||||
attrKindToAlias.insert({attrKind, {alias, {}}});
|
||||
}
|
||||
|
||||
// IntegerSet aliases
|
||||
for (auto &integerSetAliasPair : integerSetAliases) {
|
||||
if (!reservedAffineNames.match(integerSetAliasPair.first))
|
||||
registerSymbolAlias(integerSetAliasPair.first, integerSetAliasPair.second,
|
||||
integerSetIds, usedAliases, integerSetToAlias);
|
||||
// Clear the set of used identifiers so that the attribute kind aliases are
|
||||
// just a prefix and not the full alias, i.e. there may be some overlap.
|
||||
usedAliases.clear();
|
||||
|
||||
// Register the attribute aliases.
|
||||
// Create a regex for the attribute kind alias names, these have a prefix with
|
||||
// a counter appended to the end. We prevent normal aliases from having these
|
||||
// names to avoid collisions.
|
||||
llvm::Regex reservedAttrNames("[0-9]+$");
|
||||
|
||||
// Attribute value aliases.
|
||||
Attribute attr;
|
||||
for (auto &attrAliasPair : attributeAliases) {
|
||||
std::tie(attr, alias) = attrAliasPair;
|
||||
if (!reservedAttrNames.match(alias) && canRegisterAlias(alias, usedAliases))
|
||||
attrToAlias.insert({attr, {alias, kNonAttrKindAlias}});
|
||||
}
|
||||
|
||||
// Clear the set of used identifiers as types can have the same identifiers as
|
||||
// affine structures.
|
||||
usedAliases.clear();
|
||||
|
||||
// Type aliases.
|
||||
for (auto &typeAliasPair : typeAliases)
|
||||
registerSymbolAlias(typeAliasPair.first, typeAliasPair.second, usedTypes,
|
||||
usedAliases, typeToAlias);
|
||||
if (canRegisterAlias(typeAliasPair.second, usedAliases))
|
||||
typeToAlias.insert(typeAliasPair);
|
||||
}
|
||||
|
||||
// Initializes module state, populating affine map and integer set state.
|
||||
void ModuleState::initialize(Module *module) {
|
||||
// Initialize the symbol aliases.
|
||||
initializeSymbolAliases();
|
||||
|
||||
// Walk the module and visit each operation.
|
||||
for (auto &fn : *module) {
|
||||
visitType(fn.getType());
|
||||
for (auto attr : fn.getAttrs())
|
||||
ModuleState::visitAttribute(attr.second);
|
||||
for (auto attrList : fn.getAllArgAttrs())
|
||||
for (auto attr : attrList.getAttrs())
|
||||
ModuleState::visitAttribute(attr.second);
|
||||
|
||||
fn.walk([&](Operation *op) { ModuleState::visitOperation(op); });
|
||||
}
|
||||
|
||||
// Initialize the symbol aliases.
|
||||
initializeSymbolAliases();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -318,12 +357,6 @@ protected:
|
||||
void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
|
||||
ArrayRef<StringRef> elidedAttrs = {});
|
||||
void printAttributeOptionalType(Attribute attr, bool includeType);
|
||||
void printAffineMapId(int affineMapId) const;
|
||||
void printAffineMapReference(AffineMap affineMap);
|
||||
void printAffineMapAlias(StringRef alias) const;
|
||||
void printIntegerSetId(int integerSetId) const;
|
||||
void printIntegerSetReference(IntegerSet integerSet);
|
||||
void printIntegerSetAlias(StringRef alias) const;
|
||||
void printTrailingLocation(Location loc);
|
||||
void printLocationInternal(Location loc, bool pretty = false);
|
||||
void printDenseElementsAttr(DenseElementsAttr attr);
|
||||
@ -340,58 +373,6 @@ protected:
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
// Prints affine map identifier.
|
||||
void ModulePrinter::printAffineMapId(int affineMapId) const {
|
||||
os << "#map" << affineMapId;
|
||||
}
|
||||
|
||||
void ModulePrinter::printAffineMapAlias(StringRef alias) const {
|
||||
os << '#' << alias;
|
||||
}
|
||||
|
||||
void ModulePrinter::printAffineMapReference(AffineMap affineMap) {
|
||||
// Check for an affine map alias.
|
||||
auto alias = state.getAffineMapAlias(affineMap);
|
||||
if (!alias.empty())
|
||||
return printAffineMapAlias(alias);
|
||||
|
||||
int mapId = state.getAffineMapId(affineMap);
|
||||
if (mapId >= 0) {
|
||||
// Map will be printed at top of module so print reference to its id.
|
||||
printAffineMapId(mapId);
|
||||
} else {
|
||||
// Map not in module state so print inline.
|
||||
affineMap.print(os);
|
||||
}
|
||||
}
|
||||
|
||||
// Prints integer set identifier.
|
||||
void ModulePrinter::printIntegerSetId(int integerSetId) const {
|
||||
os << "#set" << integerSetId;
|
||||
}
|
||||
|
||||
void ModulePrinter::printIntegerSetAlias(StringRef alias) const {
|
||||
os << '#' << alias;
|
||||
}
|
||||
|
||||
void ModulePrinter::printIntegerSetReference(IntegerSet integerSet) {
|
||||
// Check for an integer set alias.
|
||||
auto alias = state.getIntegerSetAlias(integerSet);
|
||||
if (!alias.empty()) {
|
||||
printIntegerSetAlias(alias);
|
||||
return;
|
||||
}
|
||||
|
||||
int setId;
|
||||
if ((setId = state.getIntegerSetId(integerSet)) >= 0) {
|
||||
// The set will be printed at top of module; so print reference to its id.
|
||||
printIntegerSetId(setId);
|
||||
} else {
|
||||
// Set not in module state so print inline.
|
||||
integerSet.print(os);
|
||||
}
|
||||
}
|
||||
|
||||
void ModulePrinter::printTrailingLocation(Location loc) {
|
||||
// Check to see if we are printing debug information.
|
||||
if (!shouldPrintDebugInfoOpt)
|
||||
@ -463,31 +444,11 @@ void ModulePrinter::printLocationInternal(Location loc, bool pretty) {
|
||||
}
|
||||
|
||||
void ModulePrinter::print(Module *module) {
|
||||
for (const auto &map : state.getAffineMapIds()) {
|
||||
StringRef alias = state.getAffineMapAlias(map);
|
||||
if (!alias.empty())
|
||||
printAffineMapAlias(alias);
|
||||
else
|
||||
printAffineMapId(state.getAffineMapId(map));
|
||||
os << " = ";
|
||||
map.print(os);
|
||||
os << '\n';
|
||||
}
|
||||
for (const auto &set : state.getIntegerSetIds()) {
|
||||
StringRef alias = state.getIntegerSetAlias(set);
|
||||
if (!alias.empty())
|
||||
printIntegerSetAlias(alias);
|
||||
else
|
||||
printIntegerSetId(state.getIntegerSetId(set));
|
||||
os << " = ";
|
||||
set.print(os);
|
||||
os << '\n';
|
||||
}
|
||||
for (const auto &type : state.getTypeIds()) {
|
||||
StringRef alias = state.getTypeAlias(type);
|
||||
if (!alias.empty())
|
||||
os << '!' << alias << " = type " << type << '\n';
|
||||
}
|
||||
// Output the aliases at the top level.
|
||||
state.printAttributeAliases(os);
|
||||
state.printTypeAliases(os);
|
||||
|
||||
// Print the module.
|
||||
for (auto &fn : *module)
|
||||
print(&fn);
|
||||
}
|
||||
@ -545,6 +506,13 @@ void ModulePrinter::printAttributeOptionalType(Attribute attr,
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for an alias for this attribute.
|
||||
Twine alias = state.getAttributeAlias(attr);
|
||||
if (!alias.isTriviallyEmpty()) {
|
||||
os << '#' << alias;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (attr.getKind()) {
|
||||
case Attribute::Kind::Unit:
|
||||
os << "unit";
|
||||
@ -587,10 +555,10 @@ void ModulePrinter::printAttributeOptionalType(Attribute attr,
|
||||
os << ']';
|
||||
break;
|
||||
case Attribute::Kind::AffineMap:
|
||||
printAffineMapReference(attr.cast<AffineMapAttr>().getValue());
|
||||
attr.cast<AffineMapAttr>().getValue().print(os);
|
||||
break;
|
||||
case Attribute::Kind::IntegerSet:
|
||||
printIntegerSetReference(attr.cast<IntegerSetAttr>().getValue());
|
||||
attr.cast<IntegerSetAttr>().getValue().print(os);
|
||||
break;
|
||||
case Attribute::Kind::Type:
|
||||
printType(attr.cast<TypeAttr>().getValue());
|
||||
@ -889,7 +857,7 @@ void ModulePrinter::printType(Type type) {
|
||||
printType(v.getElementType());
|
||||
for (auto map : v.getAffineMaps()) {
|
||||
os << ", ";
|
||||
printAffineMapReference(map);
|
||||
printAttribute(AffineMapAttr::get(map));
|
||||
}
|
||||
// Only print the memory space if it is the non-default one.
|
||||
if (v.getMemorySpace())
|
||||
@ -1303,12 +1271,12 @@ void FunctionPrinter::numberValueID(Value *value) {
|
||||
Type type = op->getResult(0)->getType();
|
||||
if (auto intCst = cst.dyn_cast<IntegerAttr>()) {
|
||||
if (type.isIndex()) {
|
||||
specialName << 'c' << intCst;
|
||||
specialName << 'c' << intCst.getInt();
|
||||
} else if (type.cast<IntegerType>().isInteger(1)) {
|
||||
// i1 constants get special names.
|
||||
specialName << (intCst.getInt() ? "true" : "false");
|
||||
} else {
|
||||
specialName << 'c' << intCst << '_' << type;
|
||||
specialName << 'c' << intCst.getInt() << '_' << type;
|
||||
}
|
||||
} else if (cst.isa<FunctionAttr>()) {
|
||||
specialName << 'f';
|
||||
@ -1638,7 +1606,7 @@ void ModulePrinter::print(Function *fn) { FunctionPrinter(fn, *this).print(); }
|
||||
|
||||
void Attribute::print(raw_ostream &os) const {
|
||||
ModuleState state(/*no context is known*/ nullptr);
|
||||
ModulePrinter(os, state).printAttribute(*this);
|
||||
ModulePrinter(os, state).printAttributeAndType(*this);
|
||||
}
|
||||
|
||||
void Attribute::dump() const {
|
||||
|
@ -200,7 +200,8 @@ struct ArrayAttributeStorage : public AttributeStorage {
|
||||
struct AffineMapAttributeStorage : public AttributeStorage {
|
||||
using KeyTy = AffineMap;
|
||||
|
||||
AffineMapAttributeStorage(AffineMap value) : value(value) {}
|
||||
AffineMapAttributeStorage(AffineMap value)
|
||||
: AttributeStorage(IndexType::get(value.getContext())), value(value) {}
|
||||
|
||||
/// Key equality function.
|
||||
bool operator==(const KeyTy &key) const { return key == value; }
|
||||
|
@ -244,7 +244,7 @@ Token Lexer::lexPrefixedIdentifier(const char *tokStart) {
|
||||
switch (*tokStart) {
|
||||
case '#':
|
||||
kind = Token::hash_identifier;
|
||||
errorKind = "invalid affine map name";
|
||||
errorKind = "invalid attribute name";
|
||||
break;
|
||||
case '%':
|
||||
kind = Token::percent_identifier;
|
||||
|
@ -68,11 +68,8 @@ public:
|
||||
functionForwardRefs.clear();
|
||||
}
|
||||
|
||||
// A map from affine map identifier to AffineMap.
|
||||
llvm::StringMap<AffineMap> affineMapDefinitions;
|
||||
|
||||
// A map from integer set identifier to IntegerSet.
|
||||
llvm::StringMap<IntegerSet> integerSetDefinitions;
|
||||
// A map from attribute alias identifier to Attribute.
|
||||
llvm::StringMap<Attribute> attributeAliasDefinitions;
|
||||
|
||||
// A map from type alias identifier to Type.
|
||||
llvm::StringMap<Type> typeAliasDefinitions;
|
||||
@ -204,8 +201,6 @@ public:
|
||||
ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
|
||||
|
||||
// Polyhedral structures.
|
||||
AffineMap parseAffineMapReference();
|
||||
IntegerSet parseIntegerSetReference();
|
||||
ParseResult parseAffineMapOrIntegerSetReference(AffineMap &map,
|
||||
IntegerSet &set);
|
||||
DenseElementsAttr parseDenseElementsAttr(VectorOrTensorType type);
|
||||
@ -761,10 +756,15 @@ Type Parser::parseMemRefType() {
|
||||
// Parse affine map.
|
||||
if (parsedMemorySpace)
|
||||
return emitError("affine map after memory space in memref type");
|
||||
auto affineMap = parseAffineMapReference();
|
||||
auto affineMap = parseAttribute();
|
||||
if (!affineMap)
|
||||
return ParseFailure;
|
||||
affineMapComposition.push_back(affineMap);
|
||||
|
||||
// Verify that the parsed attribute is an affine map.
|
||||
if (auto affineMapAttr = affineMap.dyn_cast<AffineMapAttr>())
|
||||
affineMapComposition.push_back(affineMapAttr.getValue());
|
||||
else
|
||||
return emitError("expected affine map in memref type");
|
||||
}
|
||||
return ParseSuccess;
|
||||
};
|
||||
@ -1033,6 +1033,25 @@ Function *Parser::resolveFunctionReference(StringRef nameStr, SMLoc nameLoc,
|
||||
/// (tensor-type | vector-type) `,` hex-string-literal `>`
|
||||
///
|
||||
Attribute Parser::parseAttribute(Type type) {
|
||||
// If this is a hash_identifier, we are parsing an attribute alias.
|
||||
if (getToken().is(Token::hash_identifier)) {
|
||||
StringRef id = getTokenSpelling().drop_front();
|
||||
consumeToken(Token::hash_identifier);
|
||||
|
||||
// Check for an alias for this attribute.
|
||||
auto aliasIt = state.attributeAliasDefinitions.find(id);
|
||||
if (aliasIt == state.attributeAliasDefinitions.end())
|
||||
return (emitError("undefined attribute alias id '" + id + "'"), nullptr);
|
||||
|
||||
// Ensure that the attribute alias has the same type as requested.
|
||||
if (type && aliasIt->second.getType() != type) {
|
||||
emitError("requested attribute type different then alias attribute type");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return aliasIt->second;
|
||||
}
|
||||
|
||||
switch (getToken().getKind()) {
|
||||
case Token::kw_unit:
|
||||
consumeToken(Token::kw_unit);
|
||||
@ -1162,7 +1181,6 @@ Attribute Parser::parseAttribute(Type type) {
|
||||
return nullptr;
|
||||
return builder.getArrayAttr(elements);
|
||||
}
|
||||
case Token::hash_identifier:
|
||||
case Token::l_paren: {
|
||||
// Try to parse an affine map or an integer set reference.
|
||||
AffineMap map;
|
||||
@ -2071,8 +2089,8 @@ AffineParser::parseDimAndOptionalSymbolIdList(unsigned &numDims,
|
||||
|
||||
/// Parses an affine map definition inline.
|
||||
///
|
||||
/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
|
||||
/// (`size` `(` dim-size (`,` dim-size)* `)`)?
|
||||
/// affine-map ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
|
||||
/// (`size` `(` dim-size (`,` dim-size)* `)`)?
|
||||
/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
|
||||
///
|
||||
/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
|
||||
@ -2095,9 +2113,7 @@ AffineMap AffineParser::parseAffineMapInline() {
|
||||
|
||||
/// Parses an integer set definition inline.
|
||||
///
|
||||
/// integer-set-inline
|
||||
/// ::= dim-and-symbol-id-lists `:`
|
||||
/// affine-constraint-conjunction
|
||||
/// integer-set ::= dim-and-symbol-id-lists `:` affine-constraint-conjunction
|
||||
/// affine-constraint-conjunction ::= /*empty*/
|
||||
/// | affine-constraint (`,`
|
||||
/// affine-constraint)*
|
||||
@ -2149,8 +2165,8 @@ ParseResult AffineParser::parseAffineMapOrIntegerSetInline(AffineMap &map,
|
||||
|
||||
/// Parse the range and sizes affine map definition inline.
|
||||
///
|
||||
/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
|
||||
/// (`size` `(` dim-size (`,` dim-size)* `)`)?
|
||||
/// affine-map ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
|
||||
/// (`size` `(` dim-size (`,` dim-size)* `)`)?
|
||||
/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
|
||||
///
|
||||
/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
|
||||
@ -2212,77 +2228,10 @@ AffineMap AffineParser::parseAffineMapRange(unsigned numDims,
|
||||
return builder.getAffineMap(numDims, numSymbols, exprs, rangeSizes);
|
||||
}
|
||||
|
||||
/// Parse a reference to an integer set.
|
||||
/// integer-set ::= integer-set-id | integer-set-inline
|
||||
/// integer-set-id ::= `#` suffix-id
|
||||
///
|
||||
IntegerSet Parser::parseIntegerSetReference() {
|
||||
if (getToken().isNot(Token::hash_identifier)) {
|
||||
// Try to parse inline integer set.
|
||||
return AffineParser(state).parseIntegerSetInline();
|
||||
}
|
||||
|
||||
// Parse integer set identifier and verify that it exists.
|
||||
StringRef id = getTokenSpelling().drop_front();
|
||||
if (getState().integerSetDefinitions.count(id) > 0) {
|
||||
consumeToken(Token::hash_identifier);
|
||||
return getState().integerSetDefinitions[id];
|
||||
}
|
||||
|
||||
// The id isn't among any of the recorded definitions.
|
||||
emitError("undefined integer set id '" + id + "'");
|
||||
return IntegerSet();
|
||||
}
|
||||
|
||||
/// Parse a reference to an affine map.
|
||||
/// affine-map ::= affine-map-id | affine-map-inline
|
||||
/// affine-map-id ::= `#` suffix-id
|
||||
///
|
||||
AffineMap Parser::parseAffineMapReference() {
|
||||
if (getToken().isNot(Token::hash_identifier)) {
|
||||
// Try to parse inline affine map.
|
||||
return AffineParser(state).parseAffineMapInline();
|
||||
}
|
||||
|
||||
// Parse affine map identifier and verify that it exists.
|
||||
StringRef id = getTokenSpelling().drop_front();
|
||||
if (getState().affineMapDefinitions.count(id) > 0) {
|
||||
consumeToken(Token::hash_identifier);
|
||||
return getState().affineMapDefinitions[id];
|
||||
}
|
||||
|
||||
// The id isn't among any of the recorded definitions.
|
||||
emitError("undefined affine map id '" + id + "'");
|
||||
return AffineMap();
|
||||
}
|
||||
|
||||
/// Parse an ambiguous reference to either and affine map or an integer set.
|
||||
ParseResult Parser::parseAffineMapOrIntegerSetReference(AffineMap &map,
|
||||
IntegerSet &set) {
|
||||
if (getToken().isNot(Token::hash_identifier)) {
|
||||
// Try to parse inline affine map.
|
||||
return AffineParser(state).parseAffineMapOrIntegerSetInline(map, set);
|
||||
}
|
||||
|
||||
// Parse affine map / integer set identifier and verify that it exists.
|
||||
// Note that an id can't be in both affineMapDefinitions and
|
||||
// integerSetDefinitions since they use the same sigil '#'.
|
||||
StringRef id = getTokenSpelling().drop_front();
|
||||
if (getState().affineMapDefinitions.count(id) > 0) {
|
||||
consumeToken(Token::hash_identifier);
|
||||
map = getState().affineMapDefinitions[id];
|
||||
return ParseSuccess;
|
||||
}
|
||||
if (getState().integerSetDefinitions.count(id) > 0) {
|
||||
consumeToken(Token::hash_identifier);
|
||||
set = getState().integerSetDefinitions[id];
|
||||
return ParseSuccess;
|
||||
}
|
||||
|
||||
// The id isn't among any of the recorded definitions.
|
||||
emitError("undefined affine map or integer set id '" + id + "'");
|
||||
|
||||
return ParseFailure;
|
||||
return AffineParser(state).parseAffineMapOrIntegerSetInline(map, set);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -3601,7 +3550,7 @@ public:
|
||||
private:
|
||||
ParseResult finalizeModule();
|
||||
|
||||
ParseResult parseAffineStructureDef();
|
||||
ParseResult parseAttributeAliasDef();
|
||||
|
||||
ParseResult parseTypeAliasDef();
|
||||
|
||||
@ -3617,48 +3566,31 @@ private:
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
/// Parses either an affine map declaration or an integer set declaration.
|
||||
/// Parses an attribute alias declaration.
|
||||
///
|
||||
/// Affine map declaration.
|
||||
/// attribute-alias-def ::= '#' alias-name `=` attribute-value
|
||||
///
|
||||
/// affine-map-def ::= affine-map-id `=` affine-map-inline
|
||||
///
|
||||
/// Integer set declaration.
|
||||
///
|
||||
/// integer-set-decl ::= integer-set-id `=` integer-set-inline
|
||||
///
|
||||
ParseResult ModuleParser::parseAffineStructureDef() {
|
||||
ParseResult ModuleParser::parseAttributeAliasDef() {
|
||||
assert(getToken().is(Token::hash_identifier));
|
||||
|
||||
StringRef affineStructureId = getTokenSpelling().drop_front();
|
||||
StringRef attrId = getTokenSpelling().drop_front();
|
||||
|
||||
// Check for redefinitions.
|
||||
if (getState().affineMapDefinitions.count(affineStructureId) > 0)
|
||||
return emitError("redefinition of affine map id '" + affineStructureId +
|
||||
"'");
|
||||
if (getState().integerSetDefinitions.count(affineStructureId) > 0)
|
||||
return emitError("redefinition of integer set id '" + affineStructureId +
|
||||
"'");
|
||||
if (getState().attributeAliasDefinitions.count(attrId) > 0)
|
||||
return emitError("redefinition of attribute alias id '" + attrId + "'");
|
||||
|
||||
consumeToken(Token::hash_identifier);
|
||||
|
||||
// Parse the '='
|
||||
if (parseToken(Token::equal,
|
||||
"expected '=' in affine map outlined definition"))
|
||||
if (parseToken(Token::equal, "expected '=' in attribute alias definition"))
|
||||
return ParseFailure;
|
||||
|
||||
AffineMap map;
|
||||
IntegerSet set;
|
||||
if (AffineParser(getState()).parseAffineMapOrIntegerSetInline(map, set))
|
||||
// Parse the attribute value.
|
||||
Attribute attr = parseAttribute();
|
||||
if (!attr)
|
||||
return ParseFailure;
|
||||
|
||||
if (map) {
|
||||
getState().affineMapDefinitions[affineStructureId] = map;
|
||||
return ParseSuccess;
|
||||
}
|
||||
|
||||
assert(set);
|
||||
getState().integerSetDefinitions[affineStructureId] = set;
|
||||
getState().attributeAliasDefinitions[attrId] = attr;
|
||||
return ParseSuccess;
|
||||
}
|
||||
|
||||
@ -3853,7 +3785,6 @@ ParseResult ModuleParser::parseFunc() {
|
||||
/// Finish the end of module parsing - when the result is valid, do final
|
||||
/// checking.
|
||||
ParseResult ModuleParser::finalizeModule() {
|
||||
|
||||
// Resolve all forward references, building a remapping table of attributes.
|
||||
DenseMap<Attribute, FunctionAttr> remappingTable;
|
||||
for (auto forwardRef : getState().functionForwardRefs) {
|
||||
@ -3906,7 +3837,7 @@ ParseResult ModuleParser::parseModule() {
|
||||
return ParseFailure;
|
||||
|
||||
case Token::hash_identifier:
|
||||
if (parseAffineStructureDef())
|
||||
if (parseAttributeAliasDef())
|
||||
return ParseFailure;
|
||||
break;
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
#hello_world = (i, j) -> (, j) // expected-error {{expected affine expression}}
|
||||
|
||||
// -----
|
||||
#hello_world (i, j) [s0] -> (i, j) // expected-error {{expected '=' in affine map outlined definition}}
|
||||
#hello_world (i, j) [s0] -> (i, j) // expected-error {{expected '=' in attribute alias definition}}
|
||||
|
||||
// -----
|
||||
#hello_world = (i, j) [s0] -> (2*i*, 3*j*i*2 + 5) // expected-error {{missing right operand of binary op}}
|
||||
@ -118,4 +118,4 @@
|
||||
|
||||
// -----
|
||||
#ABC = (i,j) -> (i+j)
|
||||
#ABC = (i,j) -> (i+j) // expected-error {{redefinition of affine map id 'ABC'}}
|
||||
#ABC = (i,j) -> (i+j) // expected-error {{redefinition of attribute alias id 'ABC'}}
|
||||
|
@ -34,17 +34,17 @@ func @memrefs(memref<2x4xi8, >) // expected-error {{expected list element}}
|
||||
|
||||
// -----
|
||||
// Test non-existent map in memref type.
|
||||
func @memrefs(memref<2x4xi8, #map7>) // expected-error {{undefined affine map id 'map7'}}
|
||||
func @memrefs(memref<2x4xi8, #map7>) // expected-error {{undefined attribute alias id 'map7'}}
|
||||
|
||||
// -----
|
||||
// Test non hash identifier in memref type.
|
||||
func @memrefs(memref<2x4xi8, %map7>) // expected-error {{expected '(' at start of dimensional identifiers list}}
|
||||
// Test non affine map in memref type.
|
||||
func @memrefs(memref<2x4xi8, i8>) // expected-error {{expected affine map in memref type}}
|
||||
|
||||
// -----
|
||||
// Test non-existent map in map composition of memref type.
|
||||
#map0 = (d0, d1) -> (d0, d1)
|
||||
|
||||
func @memrefs(memref<2x4xi8, #map0, #map8>) // expected-error {{undefined affine map id 'map8'}}
|
||||
func @memrefs(memref<2x4xi8, #map0, #map8>) // expected-error {{undefined attribute alias id 'map8'}}
|
||||
|
||||
// -----
|
||||
// Test multiple memory space error.
|
||||
|
Loading…
x
Reference in New Issue
Block a user