diff --git a/mlir/include/mlir/IR/BuiltinAttributes.td b/mlir/include/mlir/IR/BuiltinAttributes.td --- a/mlir/include/mlir/IR/BuiltinAttributes.td +++ b/mlir/include/mlir/IR/BuiltinAttributes.td @@ -817,10 +817,25 @@ return $_get(type.getContext(), bytes, type); }]>, AttrBuilder<(ins "StringRef":$bytes), [{ + if (bytes.empty()) + return get($_ctxt); return $_get($_ctxt, bytes, NoneType::get($_ctxt)); - }]> + }]>, + + /// Build an empty string attr with NoneType. + AttrBuilder<(ins)> ]; - let extraClassDeclaration = "using ValueType = StringRef;"; + let extraClassDeclaration = [{ + using ValueType = StringRef; + + private: + /// Return an empty StringAttr with NoneType type. This is a special variant + /// of the `get` method that is used by the MLIRContext to cache the + /// instance. + static StringAttr getEmptyStringAttrUnchecked(MLIRContext *context); + friend MLIRContext; + public: + }]; let skipDefaultBuilders = 1; } diff --git a/mlir/lib/IR/BuiltinAttributes.cpp b/mlir/lib/IR/BuiltinAttributes.cpp --- a/mlir/lib/IR/BuiltinAttributes.cpp +++ b/mlir/lib/IR/BuiltinAttributes.cpp @@ -196,6 +196,10 @@ return Base::get(context, ArrayRef()); } +StringAttr StringAttr::getEmptyStringAttrUnchecked(MLIRContext *context) { + return Base::get(context, "", NoneType::get(context)); +} + //===----------------------------------------------------------------------===// // FloatAttr //===----------------------------------------------------------------------===// diff --git a/mlir/lib/IR/MLIRContext.cpp b/mlir/lib/IR/MLIRContext.cpp --- a/mlir/lib/IR/MLIRContext.cpp +++ b/mlir/lib/IR/MLIRContext.cpp @@ -332,6 +332,7 @@ UnitAttr unitAttr; UnknownLoc unknownLocAttr; DictionaryAttr emptyDictionaryAttr; + StringAttr emptyStringAttr; public: MLIRContextImpl() : identifiers(identifierAllocator) {} @@ -400,6 +401,8 @@ impl->unitAttr = AttributeUniquer::get(this); /// The empty dictionary attribute. impl->emptyDictionaryAttr = DictionaryAttr::getEmptyUnchecked(this); + /// The empty string attribute. + impl->emptyStringAttr = StringAttr::getEmptyStringAttrUnchecked(this); // Register the affine storage objects with the uniquer. impl->affineUniquer @@ -929,6 +932,11 @@ return context->getImpl().emptyDictionaryAttr; } +/// Return an empty string. +StringAttr StringAttr::get(MLIRContext *context) { + return context->getImpl().emptyStringAttr; +} + //===----------------------------------------------------------------------===// // AffineMap uniquing //===----------------------------------------------------------------------===//