From 94afc426e2643f29a426e3cde458e2f064147dfd Mon Sep 17 00:00:00 2001 From: River Riddle Date: Mon, 6 May 2019 10:36:32 -0700 Subject: [PATCH] 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 --- mlir/include/mlir/IR/Dialect.h | 17 +- mlir/lib/IR/AsmPrinter.cpp | 322 ++++++++++++++++-------------------- mlir/lib/IR/AttributeDetail.h | 3 +- mlir/lib/Parser/Lexer.cpp | 2 +- mlir/lib/Parser/Parser.cpp | 163 ++++++------------ mlir/test/IR/invalid-affinemap.mlir | 4 +- mlir/test/IR/invalid.mlir | 8 +- 7 files changed, 211 insertions(+), 308 deletions(-) diff --git a/mlir/include/mlir/IR/Dialect.h b/mlir/include/mlir/IR/Dialect.h index f562bb8..6a4fdf7 100644 --- a/mlir/include/mlir/IR/Dialect.h +++ b/mlir/include/mlir/IR/Dialect.h @@ -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> &aliases) {} - /// Hook for defining IntegerSet aliases. - virtual void getIntegerSetAliases( - SmallVectorImpl> &aliases) {} + /// Hook for defining Attribute kind aliases. This will generate an alias for + /// all attributes of the given kind in the form : [0-9]+. These + /// aliases must not contain `.`. + virtual void getAttributeKindAliases( + SmallVectorImpl> &aliases) {} + /// Hook for defining Attribute aliases. These aliases must not contain `.` or + /// end with a numeric digit([0-9]+). + virtual void getAttributeAliases( + SmallVectorImpl> &aliases) {} /// Hook for defining Type aliases. virtual void - getTypeAliases(SmallVectorImpl> &aliases) {} + getTypeAliases(SmallVectorImpl> &aliases) {} /// Verify an attribute from this dialect on the given function. Returns /// failure if the verification failed, success otherwise. diff --git a/mlir/lib/IR/AsmPrinter.cpp b/mlir/lib/IR/AsmPrinter.cpp index d97b2fc..aeec1ab 100644 --- a/mlir/lib/IR/AsmPrinter.cpp +++ b/mlir/lib/IR/AsmPrinter.cpp @@ -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 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); - } - - int getAffineMapId(AffineMap affineMap) const { - auto it = affineMapIds.find(affineMap); - if (it == affineMapIds.end()) { - return -1; + 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)); + } + + 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 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 getIntegerSetIds() const { return integerSetsById; } - StringRef getTypeAlias(Type ty) const { return typeToAlias.lookup(ty); } - ArrayRef 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(attr.getKind())); + if (alias == attrKindToAlias.end()) + return; + std::pair 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 affineMapIds; - std::vector affineMapsById; - DenseMap affineMapToAlias; + /// Set of attributes known to be used within the module. + llvm::SetVector usedAttributes; - DenseMap integerSetIds; - std::vector integerSetsById; - DenseMap 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> 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>> + attrKindToAlias; + + /// Set of types known to be used within the module. llvm::SetVector usedTypes; + + /// A mapping between a type and a given alias. DenseMap typeToAlias; }; } // end anonymous namespace @@ -169,24 +198,18 @@ void ModuleState::visitType(Type type) { visitType(result); } else if (auto memref = type.dyn_cast()) { // 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()) { visitType(vecOrTensor.getElementType()); } } void ModuleState::visitAttribute(Attribute attr) { - if (auto mapAttr = attr.dyn_cast()) { - recordAffineMapReference(mapAttr.getValue()); - } else if (auto setAttr = attr.dyn_cast()) { - recordIntegerSetReference(setAttr.getValue()); - } else if (auto arrayAttr = attr.dyn_cast()) { - for (auto elt : arrayAttr.getValue()) { + recordAttributeReference(attr); + if (auto arrayAttr = attr.dyn_cast()) + 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 -static void registerSymbolAlias(StringRef name, SymbolTy sym, - SymbolsInModuleSetTy &symbolsInModuleSet, - llvm::StringSet<> &usedAliases, - DenseMap &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, 8> affineMapAliases; - SmallVector, 8> integerSetAliases; - SmallVector, 16> typeAliases; + SmallVector, 8> attributeKindAliases; + SmallVector, 8> attributeAliases; + SmallVector, 16> typeAliases; + + // AffineMap/Integer set have specific kind aliases. + attributeKindAliases.emplace_back( + static_cast(Attribute::Kind::AffineMap), "map"); + attributeKindAliases.emplace_back( + static_cast(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 attrs, ArrayRef 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().getValue()); + attr.cast().getValue().print(os); break; case Attribute::Kind::IntegerSet: - printIntegerSetReference(attr.cast().getValue()); + attr.cast().getValue().print(os); break; case Attribute::Kind::Type: printType(attr.cast().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()) { if (type.isIndex()) { - specialName << 'c' << intCst; + specialName << 'c' << intCst.getInt(); } else if (type.cast().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()) { 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 { diff --git a/mlir/lib/IR/AttributeDetail.h b/mlir/lib/IR/AttributeDetail.h index 990008b..d1802f4 100644 --- a/mlir/lib/IR/AttributeDetail.h +++ b/mlir/lib/IR/AttributeDetail.h @@ -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; } diff --git a/mlir/lib/Parser/Lexer.cpp b/mlir/lib/Parser/Lexer.cpp index 59a435e..0c76cca 100644 --- a/mlir/lib/Parser/Lexer.cpp +++ b/mlir/lib/Parser/Lexer.cpp @@ -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; diff --git a/mlir/lib/Parser/Parser.cpp b/mlir/lib/Parser/Parser.cpp index 15807f6..9229236 100644 --- a/mlir/lib/Parser/Parser.cpp +++ b/mlir/lib/Parser/Parser.cpp @@ -68,11 +68,8 @@ public: functionForwardRefs.clear(); } - // A map from affine map identifier to AffineMap. - llvm::StringMap affineMapDefinitions; - - // A map from integer set identifier to IntegerSet. - llvm::StringMap integerSetDefinitions; + // A map from attribute alias identifier to Attribute. + llvm::StringMap attributeAliasDefinitions; // A map from type alias identifier to Type. llvm::StringMap typeAliasDefinitions; @@ -204,8 +201,6 @@ public: ParseResult parseAttributeDict(SmallVectorImpl &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()) + 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. -/// -/// Affine map declaration. +/// Parses an attribute alias declaration. /// -/// affine-map-def ::= affine-map-id `=` affine-map-inline +/// attribute-alias-def ::= '#' alias-name `=` attribute-value /// -/// 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 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; diff --git a/mlir/test/IR/invalid-affinemap.mlir b/mlir/test/IR/invalid-affinemap.mlir index b70bb7a..f48ec3a 100644 --- a/mlir/test/IR/invalid-affinemap.mlir +++ b/mlir/test/IR/invalid-affinemap.mlir @@ -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'}} diff --git a/mlir/test/IR/invalid.mlir b/mlir/test/IR/invalid.mlir index efb5217..1288fe0 100644 --- a/mlir/test/IR/invalid.mlir +++ b/mlir/test/IR/invalid.mlir @@ -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. -- 2.7.4