[Mlir-commits] [mlir] 8fe5093 - [mlir][Linalg] Split explicit inherent/discardable attribute APIs access (#218916)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Wed Aug 26 15:55:46 PDT 2026
Author: Mehdi Amini
Date: 2026-08-26T22:55:41Z
New Revision: 8fe50937417b74c835fa9fcfb12aae9fe46af3f0
URL: https://github.com/llvm/llvm-project/commit/8fe50937417b74c835fa9fcfb12aae9fe46af3f0
DIFF: https://github.com/llvm/llvm-project/commit/8fe50937417b74c835fa9fcfb12aae9fe46af3f0.diff
LOG: [mlir][Linalg] Split explicit inherent/discardable attribute APIs access (#218916)
Migrate Linalg, Bufferization, and MemRef users to explicit discardable
or operation-specific attribute access, including the Linalg generator
and C API.
Assisted-by: Codex
Added:
Modified:
mlir/include/mlir/IR/OpImplementation.h
mlir/include/mlir/IR/Operation.h
mlir/lib/CAPI/Dialect/Linalg.cpp
mlir/lib/Conversion/LinalgToStandard/LinalgToStandard.cpp
mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp
mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp
mlir/lib/Dialect/Bufferization/Transforms/OneShotModuleBufferize.cpp
mlir/lib/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation.cpp
mlir/lib/Dialect/Linalg/IR/LinalgInterfaces.cpp
mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
mlir/lib/Dialect/Linalg/Transforms/BufferizableOpInterfaceImpl.cpp
mlir/lib/Dialect/Linalg/Transforms/DropUnitDims.cpp
mlir/lib/Dialect/Linalg/Transforms/ElementwiseToLinalg.cpp
mlir/lib/Dialect/Linalg/Transforms/EraseUnusedOperandsAndResults.cpp
mlir/lib/Dialect/Linalg/Transforms/FoldIntoElementwise.cpp
mlir/lib/Dialect/Linalg/Transforms/SimplifyDepthwiseConv.cpp
mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp
mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp
mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp
mlir/lib/Dialect/MemRef/Transforms/AllocationOpInterfaceImpl.cpp
mlir/lib/Dialect/MemRef/Transforms/MultiBuffer.cpp
mlir/lib/Dialect/MemRef/Transforms/NormalizeMemRefs.cpp
mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir
mlir/test/Dialect/Linalg/library-calls.mlir
mlir/test/Dialect/Linalg/rank-reduce-contraction-ops.mlir
mlir/test/Dialect/MemRef/multibuffer.mlir
mlir/test/lib/Dialect/Bufferization/TestTensorLikeAndBufferLike.cpp
mlir/test/mlir-linalg-ods-gen/test-linalg-ods-yaml-gen.yaml
mlir/tools/mlir-linalg-ods-gen/mlir-linalg-ods-yaml-gen.cpp
mlir/unittests/Dialect/Linalg/InferConvolutionDimsTest.cpp
mlir/unittests/IR/OperationSupportTest.cpp
Removed:
################################################################################
diff --git a/mlir/include/mlir/IR/OpImplementation.h b/mlir/include/mlir/IR/OpImplementation.h
index 6e0f001f83ba9..ce26c4b4c9cbf 100644
--- a/mlir/include/mlir/IR/OpImplementation.h
+++ b/mlir/include/mlir/IR/OpImplementation.h
@@ -502,6 +502,11 @@ class OpAsmPrinter : public AsmPrinter {
virtual void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
ArrayRef<StringRef> elidedAttrs = {}) = 0;
+ void printOptionalAttrDict(DictionaryAttr attrs,
+ ArrayRef<StringRef> elidedAttrs = {}) {
+ printOptionalAttrDict(attrs.getValue(), elidedAttrs);
+ }
+
/// If the specified operation has attributes, print out an attribute
/// dictionary prefixed with 'attributes'.
virtual void
diff --git a/mlir/include/mlir/IR/Operation.h b/mlir/include/mlir/IR/Operation.h
index 92a716e8b0c23..3ea9ad8ca0cfc 100644
--- a/mlir/include/mlir/IR/Operation.h
+++ b/mlir/include/mlir/IR/Operation.h
@@ -467,6 +467,13 @@ class alignas(8) Operation final
/// to use Properties instead.
std::optional<Attribute> getInherentAttr(StringRef name);
+ /// Access an inherent attribute by name and cast it to `AttrClass`.
+ template <typename AttrClass>
+ AttrClass getInherentAttrOfType(StringRef name) {
+ return llvm::dyn_cast_or_null<AttrClass>(
+ getInherentAttr(name).value_or(Attribute{}));
+ }
+
/// Set an inherent attribute by name.
///
/// This method is available as a transient facility in the migration process
diff --git a/mlir/lib/CAPI/Dialect/Linalg.cpp b/mlir/lib/CAPI/Dialect/Linalg.cpp
index 92ead3eed9a95..7a66f368459c6 100644
--- a/mlir/lib/CAPI/Dialect/Linalg.cpp
+++ b/mlir/lib/CAPI/Dialect/Linalg.cpp
@@ -39,7 +39,10 @@ void mlirLinalgFillBuiltinNamedOpRegion(MlirOperation mlirOp) {
Region ®ion = op->getRegion(0);
Block *body = b.createBlock(®ion, /*insertPt=*/{}, argTypes, argLocs);
b.setInsertionPointToStart(body);
- fun(b, *body, op->getAttrs(), /*emitError=*/{});
+ NamedAttrList attrs;
+ op->getName().walkInherentAttrs(
+ op, [&](StringRef name, Attribute &attr) { attrs.append(name, attr); });
+ fun(b, *body, attrs, /*emitError=*/{});
}
MLIR_CAPI_EXPORTED bool mlirLinalgIsAContractionOp(MlirOperation op) {
diff --git a/mlir/lib/Conversion/LinalgToStandard/LinalgToStandard.cpp b/mlir/lib/Conversion/LinalgToStandard/LinalgToStandard.cpp
index 54c554eb6bd93..b5b2b0ba2c277 100644
--- a/mlir/lib/Conversion/LinalgToStandard/LinalgToStandard.cpp
+++ b/mlir/lib/Conversion/LinalgToStandard/LinalgToStandard.cpp
@@ -83,8 +83,8 @@ getLibraryCallSymbolRef(Operation *op, PatternRewriter &rewriter) {
// Insert a function attribute that will trigger the emission of the
// corresponding `_mlir_ciface_xxx` interface so that external libraries see
// a normalized ABI. This interface is added during std to llvm conversion.
- funcOp->setAttr(LLVM::LLVMDialect::getEmitCWrapperAttrName(),
- UnitAttr::get(op->getContext()));
+ funcOp->setDiscardableAttr(LLVM::LLVMDialect::getEmitCWrapperAttrName(),
+ UnitAttr::get(op->getContext()));
funcOp.setPrivate();
return fnNameAttr;
}
diff --git a/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp b/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp
index 8ca968367b026..e76b51aa8015d 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp
@@ -332,10 +332,10 @@ struct CallOpInterface
}
// 3. Create the new CallOp.
- Operation *newCallOp =
- func::CallOp::create(rewriter, callOp.getLoc(), funcOp.getSymName(),
- resultTypes, newOperands);
- newCallOp->setAttrs(callOp->getAttrs());
+ func::CallOp newCallOp =
+ func::CallOp::create(rewriter, callOp.getLoc(), resultTypes,
+ newOperands, callOp.getProperties(),
+ callOp->getDiscardableAttrDictionary().getValue());
// 4. Replace the old op with the new op.
replaceOpWithBufferizedValues(rewriter, callOp, newCallOp->getResults());
diff --git a/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp b/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp
index 57ef3b88b291c..937a765d49ad8 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp
@@ -89,7 +89,7 @@ constexpr StringLiteral kBbArgAliasSetAttrName = "__bbarg_alias_set_attr__";
static void setInPlaceOpOperand(OpOperand &opOperand, bool inPlace) {
Operation *op = opOperand.getOwner();
SmallVector<StringRef> inPlaceVector;
- if (auto attr = op->getAttr(kInPlaceOperandsAttrName)) {
+ if (auto attr = op->getDiscardableAttr(kInPlaceOperandsAttrName)) {
inPlaceVector = SmallVector<StringRef>(llvm::to_vector<4>(
cast<ArrayAttr>(attr).getAsValueRange<StringAttr>()));
// The existing attribute may have fewer entries than the current operand
@@ -104,8 +104,8 @@ static void setInPlaceOpOperand(OpOperand &opOperand, bool inPlace) {
inPlaceVector[opOperand.getOperandNumber()] = "false";
}
inPlaceVector[opOperand.getOperandNumber()] = inPlace ? "true" : "false";
- op->setAttr(kInPlaceOperandsAttrName,
- OpBuilder(op).getStrArrayAttr(inPlaceVector));
+ op->setDiscardableAttr(kInPlaceOperandsAttrName,
+ OpBuilder(op).getStrArrayAttr(inPlaceVector));
}
//===----------------------------------------------------------------------===//
@@ -446,21 +446,23 @@ static void annotateConflict(OpOperand *uRead, OpOperand *uConflictingWrite,
id +
"[CONFL-WRITE: " + std::to_string(uConflictingWrite->getOperandNumber()) +
"]";
- conflictingWritingOp->setAttr(conflictingWriteAttr, b.getUnitAttr());
+ conflictingWritingOp->setDiscardableAttr(conflictingWriteAttr,
+ b.getUnitAttr());
std::string readAttr =
id + "[READ: " + std::to_string(uRead->getOperandNumber()) + "]";
- readingOp->setAttr(readAttr, b.getUnitAttr());
+ readingOp->setDiscardableAttr(readAttr, b.getUnitAttr());
if (auto opResult = dyn_cast<OpResult>(definition)) {
std::string defAttr =
id + "[DEF: result " + std::to_string(opResult.getResultNumber()) + "]";
- opResult.getDefiningOp()->setAttr(defAttr, b.getUnitAttr());
+ opResult.getDefiningOp()->setDiscardableAttr(defAttr, b.getUnitAttr());
} else {
auto bbArg = cast<BlockArgument>(definition);
std::string defAttr =
id + "[DEF: bbArg " + std::to_string(bbArg.getArgNumber()) + "]";
- bbArg.getOwner()->getParentOp()->setAttr(defAttr, b.getUnitAttr());
+ bbArg.getOwner()->getParentOp()->setDiscardableAttr(defAttr,
+ b.getUnitAttr());
}
}
@@ -908,12 +910,12 @@ static void annotateNonWritableTensor(Value value) {
if (auto opResult = dyn_cast<OpResult>(value)) {
std::string attr = id + "[NOT-WRITABLE: result " +
std::to_string(opResult.getResultNumber()) + "]";
- opResult.getDefiningOp()->setAttr(attr, b.getUnitAttr());
+ opResult.getDefiningOp()->setDiscardableAttr(attr, b.getUnitAttr());
} else {
auto bbArg = cast<BlockArgument>(value);
std::string attr = id + "[NOT-WRITABLE: bbArg " +
std::to_string(bbArg.getArgNumber()) + "]";
- bbArg.getOwner()->getParentOp()->setAttr(attr, b.getUnitAttr());
+ bbArg.getOwner()->getParentOp()->setDiscardableAttr(attr, b.getUnitAttr());
}
}
@@ -1299,7 +1301,8 @@ static void annotateOpsWithAliasSets(Operation *op,
}
}
if (!opResultAliasSets.empty())
- op->setAttr(kOpResultAliasSetAttrName, b.getArrayAttr(opResultAliasSets));
+ op->setDiscardableAttr(kOpResultAliasSetAttrName,
+ b.getArrayAttr(opResultAliasSets));
// Build alias set array for every BlockArgument.
SmallVector<Attribute> regionAliasSets;
@@ -1319,7 +1322,8 @@ static void annotateOpsWithAliasSets(Operation *op,
regionAliasSets.push_back(b.getArrayAttr(blockAliasSets));
}
if (hasTensorBbArg)
- op->setAttr(kBbArgAliasSetAttrName, b.getArrayAttr(regionAliasSets));
+ op->setDiscardableAttr(kBbArgAliasSetAttrName,
+ b.getArrayAttr(regionAliasSets));
});
}
diff --git a/mlir/lib/Dialect/Bufferization/Transforms/OneShotModuleBufferize.cpp b/mlir/lib/Dialect/Bufferization/Transforms/OneShotModuleBufferize.cpp
index 5552246427188..41d9a37844c9a 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/OneShotModuleBufferize.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/OneShotModuleBufferize.cpp
@@ -99,8 +99,8 @@ static void annotateEquivalentReturnBbArg(OpOperand &returnVal,
Operation *op = returnVal.getOwner();
SmallVector<int64_t> equivBbArgs;
- if (op->hasAttr(kEquivalentArgsAttr)) {
- auto attr = cast<ArrayAttr>(op->getAttr(kEquivalentArgsAttr));
+ if (op->hasDiscardableAttr(kEquivalentArgsAttr)) {
+ auto attr = cast<ArrayAttr>(op->getDiscardableAttr(kEquivalentArgsAttr));
equivBbArgs = llvm::map_to_vector<4>(attr, [](Attribute a) {
return cast<IntegerAttr>(a).getValue().getSExtValue();
});
@@ -110,7 +110,7 @@ static void annotateEquivalentReturnBbArg(OpOperand &returnVal,
equivBbArgs[returnVal.getOperandNumber()] = bbArg.getArgNumber();
OpBuilder b(op->getContext());
- op->setAttr(kEquivalentArgsAttr, b.getI64ArrayAttr(equivBbArgs));
+ op->setDiscardableAttr(kEquivalentArgsAttr, b.getI64ArrayAttr(equivBbArgs));
}
/// Store function BlockArguments that are equivalent to/aliasing a returned
diff --git a/mlir/lib/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation.cpp b/mlir/lib/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation.cpp
index 7b8340e363e39..d7aba40313a47 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation.cpp
@@ -674,10 +674,10 @@ Operation *BufferDeallocation::appendOpResults(Operation *op,
SmallVector<Value> oldResults(op->getResults());
newTypes.append(types.begin(), types.end());
- auto *newOp = Operation::create(op->getLoc(), op->getName(), newTypes,
- op->getOperands(), op->getAttrDictionary(),
- op->getPropertiesStorage(),
- op->getSuccessors(), op->getNumRegions());
+ auto *newOp = Operation::create(
+ op->getLoc(), op->getName(), newTypes, op->getOperands(),
+ op->getDiscardableAttrDictionary(), op->getPropertiesStorage(),
+ op->getSuccessors(), op->getNumRegions());
for (auto [oldRegion, newRegion] :
llvm::zip(op->getRegions(), newOp->getRegions()))
newRegion.takeBody(oldRegion);
@@ -875,7 +875,7 @@ BufferDeallocation::handleInterface(MemoryEffectOpInterface op) {
// usually forbidden in the input IR (not supported by the buffer
// deallocation pass). However, if they are under manual deallocation,
// they can be safely ignored by the buffer deallocation pass.
- if (!op->hasAttr(BufferizationDialect::kManualDeallocation))
+ if (!op->hasDiscardableAttr(BufferizationDialect::kManualDeallocation))
return op->emitError(
"memory free side-effect on MemRef value not supported!");
@@ -913,7 +913,7 @@ BufferDeallocation::handleInterface(MemoryEffectOpInterface op) {
continue;
}
- if (op->hasAttr(BufferizationDialect::kManualDeallocation)) {
+ if (op->hasDiscardableAttr(BufferizationDialect::kManualDeallocation)) {
// This allocation will be deallocated manually. Assign an ownership of
// "false", so that it will never be deallocated by the buffer
// deallocation pass.
diff --git a/mlir/lib/Dialect/Linalg/IR/LinalgInterfaces.cpp b/mlir/lib/Dialect/Linalg/IR/LinalgInterfaces.cpp
index e3f4988b3ab76..3045e65630cf2 100644
--- a/mlir/lib/Dialect/Linalg/IR/LinalgInterfaces.cpp
+++ b/mlir/lib/Dialect/Linalg/IR/LinalgInterfaces.cpp
@@ -854,6 +854,12 @@ static FailureOr<ConvolutionDimensions> inferConvolutionDimsImpl(
return dimensions;
}
+static DenseIntElementsAttr getInherentConvolutionAttr(LinalgOp linalgOp,
+ StringRef name) {
+ return dyn_cast_or_null<DenseIntElementsAttr>(
+ linalgOp->getInherentAttr(name).value_or(Attribute{}));
+}
+
/// Find at least 1 parallel (output_image) and reduction (filter_loop)
/// dimension candidates that form a convolution subcomputation within
/// `linalgOp`. The LHS is assumed to be the convolution input while the
@@ -898,8 +904,8 @@ mlir::linalg::inferConvolutionDims(LinalgOp linalgOp) {
return inferConvolutionDimsImpl(
indexingMaps, linalgOp.getIteratorTypesArray(), inputExprWalker,
/*allowEmptyConvolvedDims=*/false,
- linalgOp->getAttrOfType<DenseIntElementsAttr>("strides"),
- linalgOp->getAttrOfType<DenseIntElementsAttr>("dilations"));
+ getInherentConvolutionAttr(linalgOp, "strides"),
+ getInherentConvolutionAttr(linalgOp, "dilations"));
}
FailureOr<ConvolutionDimensions>
@@ -1067,8 +1073,8 @@ mlir::linalg::detail::isConvolutionInterfaceImpl(
if (dimensions) {
FailureOr<ConvolutionDimensions> res = inferConvolutionDimsImpl(
indexingMaps, iteratorTypes, inputExprWalker, allowEmptyConvolvedDims,
- linalgOp->getAttrOfType<DenseIntElementsAttr>("strides"),
- linalgOp->getAttrOfType<DenseIntElementsAttr>("dilations"));
+ getInherentConvolutionAttr(linalgOp, "strides"),
+ getInherentConvolutionAttr(linalgOp, "dilations"));
assert(succeeded(res) && "unexpected failure to infer convolution dims");
*dimensions = *res;
}
diff --git a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
index af670b8d4fae7..9ff7f1f07a425 100644
--- a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
+++ b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
@@ -424,7 +424,10 @@ static void printNamedStructuredOpResults(OpAsmPrinter &p,
static void printNamedStructuredOp(OpAsmPrinter &p, Operation *op,
ValueRange inputs, ValueRange outputs,
ArrayRef<StringRef> elidedAttrs = {}) {
- p.printOptionalAttrDict(op->getAttrs(), elidedAttrs);
+ NamedAttrList attrs(op->getDiscardableAttrDictionary());
+ op->getName().walkInherentAttrs(
+ op, [&](StringRef name, Attribute &attr) { attrs.append(name, attr); });
+ p.printOptionalAttrDict(attrs, elidedAttrs);
// Printing is shared with generic ops, except for the region and
// attributes.
@@ -1224,7 +1227,11 @@ void GenericOp::print(OpAsmPrinter &p) {
llvm::StringSet<> genericAttrNamesSet;
genericAttrNamesSet.insert_range(genericAttrNames);
SmallVector<NamedAttribute, 8> genericAttrs;
- for (auto attr : (*this)->getAttrs()) {
+ for (StringRef attrName : genericAttrNames) {
+ std::optional<Attribute> value = (*this)->getInherentAttr(attrName);
+ if (!value || !*value)
+ continue;
+ NamedAttribute attr{StringAttr::get(getContext(), attrName), *value};
if (attr.getName() == getIteratorTypesAttrName()) {
auto iteratorTypes =
llvm::cast<ArrayAttr>(attr.getValue())
@@ -1257,13 +1264,13 @@ void GenericOp::print(OpAsmPrinter &p) {
genericAttrNamesSet.insert(genericAttrNames.back());
bool hasExtraAttrs = false;
- for (NamedAttribute n : (*this)->getAttrs()) {
+ for (NamedAttribute n : (*this)->getDiscardableAttrDictionary()) {
if ((hasExtraAttrs = !genericAttrNamesSet.contains(n.getName().strref())))
break;
}
if (hasExtraAttrs) {
p << " attrs = ";
- p.printOptionalAttrDict((*this)->getAttrs(),
+ p.printOptionalAttrDict((*this)->getDiscardableAttrDictionary(),
/*elidedAttrs=*/genericAttrNames);
}
@@ -1673,8 +1680,12 @@ static bool canUseShortForm(Block *body, bool initFirst = false,
static void printShortForm(OpAsmPrinter &p, Operation *payloadOp) {
SmallVector<StringRef> elidedAttrs;
std::string attrToElide;
+ NamedAttrList attrs(payloadOp->getDiscardableAttrDictionary());
+ payloadOp->getName().walkInherentAttrs(
+ payloadOp,
+ [&](StringRef name, Attribute &attr) { attrs.append(name, attr); });
p << " { " << payloadOp->getName().getStringRef();
- for (const auto &attr : payloadOp->getAttrs()) {
+ for (const auto &attr : attrs) {
auto fastAttr =
llvm::dyn_cast<mlir::arith::FastMathFlagsAttr>(attr.getValue());
if (fastAttr && fastAttr.getValue() == mlir::arith::FastMathFlags::none) {
@@ -1683,7 +1694,7 @@ static void printShortForm(OpAsmPrinter &p, Operation *payloadOp) {
break;
}
}
- p.printOptionalAttrDict(payloadOp->getAttrs(), elidedAttrs);
+ p.printOptionalAttrDict(attrs, elidedAttrs);
p << " }";
}
@@ -1696,7 +1707,7 @@ void MapOp::print(OpAsmPrinter &p) {
}
printCommonStructuredOpParts(p, getDpsInputs(), getDpsInits());
- p.printOptionalAttrDict((*this)->getAttrs());
+ p.printOptionalAttrDict((*this)->getDiscardableAttrDictionary());
if (!useShortForm) {
// Print region if the payload op was not detected.
@@ -1906,7 +1917,8 @@ void ReduceOp::print(OpAsmPrinter &p) {
printCommonStructuredOpParts(p, getDpsInputs(), getDpsInits());
printDenseI64ArrayAttr(p, getDimensionsAttrName(), getDimensions());
- p.printOptionalAttrDict((*this)->getAttrs(), {getDimensionsAttrName()});
+ p.printOptionalAttrDict((*this)->getDiscardableAttrDictionary(),
+ {getDimensionsAttrName()});
if (!useShortForm) {
// Print region if the payload op was not detected.
p.increaseIndent();
@@ -2085,7 +2097,8 @@ void TransposeOp::getAsmResultNames(
void TransposeOp::print(OpAsmPrinter &p) {
printCommonStructuredOpParts(p, getDpsInputs(), getDpsInits());
printDenseI64ArrayAttr(p, getPermutationAttrName(), getPermutation());
- p.printOptionalAttrDict((*this)->getAttrs(), {getPermutationAttrName()});
+ p.printOptionalAttrDict((*this)->getDiscardableAttrDictionary(),
+ {getPermutationAttrName()});
}
LogicalResult TransposeOp::verify() {
@@ -2333,7 +2346,8 @@ void BroadcastOp::getAsmResultNames(
void BroadcastOp::print(OpAsmPrinter &p) {
printCommonStructuredOpParts(p, getDpsInputs(), getDpsInits());
printDenseI64ArrayAttr(p, getDimensionsAttrName(), getDimensions());
- p.printOptionalAttrDict((*this)->getAttrs(), {getDimensionsAttrName()});
+ p.printOptionalAttrDict((*this)->getDiscardableAttrDictionary(),
+ {getDimensionsAttrName()});
}
LogicalResult BroadcastOp::verify() {
@@ -2481,7 +2495,7 @@ void BroadcastOp::getCanonicalizationPatterns(RewritePatternSet &results,
void linalg::YieldOp::print(OpAsmPrinter &p) {
if (getNumOperands() > 0)
p << ' ' << getOperands();
- p.printOptionalAttrDict((*this)->getAttrs());
+ p.printOptionalAttrDict((*this)->getDiscardableAttrDictionary());
if (getNumOperands() > 0)
p << " : " << getOperandTypes();
}
@@ -2642,13 +2656,13 @@ std::string mlir::linalg::generateLibraryCallName(Operation *op) {
assert(isa<LinalgOp>(op));
std::string name(op->getName().getStringRef().str());
std::string fun = "";
- for (NamedAttribute kv : op->getAttrs()) {
- if (UnaryFnAttr ufa = llvm::dyn_cast<UnaryFnAttr>(kv.getValue())) {
+ op->getName().walkInherentAttrs(op, [&](StringRef, Attribute &attr) {
+ if (UnaryFnAttr ufa = llvm::dyn_cast<UnaryFnAttr>(attr)) {
fun = stringifyEnum(ufa.getValue()).str() + "_";
- } else if (BinaryFnAttr bfa = llvm::dyn_cast<BinaryFnAttr>(kv.getValue())) {
+ } else if (BinaryFnAttr bfa = llvm::dyn_cast<BinaryFnAttr>(attr)) {
fun = stringifyEnum(bfa.getValue()).str() + "_";
}
- }
+ });
name.reserve(128);
llvm::replace(name, '.', '_');
llvm::raw_string_ostream ss(name);
@@ -4217,9 +4231,9 @@ MatmulTransposeAOp::create(OpBuilder &builder, Location location,
}
bool MatmulTransposeAOp::classof(Operation *op) {
- return dyn_cast_or_null<linalg::MatmulOp>(op) &&
- MatmulTransposeAOp::isDefaultIndexingMaps(
- op->getAttr("indexing_maps"));
+ auto matmulOp = dyn_cast_or_null<linalg::MatmulOp>(op);
+ return matmulOp && MatmulTransposeAOp::isDefaultIndexingMaps(
+ matmulOp.getIndexingMapsAttr());
}
SmallVector<AffineMap>
@@ -4311,9 +4325,9 @@ MatmulTransposeBOp::create(OpBuilder &builder, Location location,
}
bool MatmulTransposeBOp::classof(Operation *op) {
- return dyn_cast_or_null<linalg::MatmulOp>(op) &&
- MatmulTransposeBOp::isDefaultIndexingMaps(
- op->getAttr("indexing_maps"));
+ auto matmulOp = dyn_cast_or_null<linalg::MatmulOp>(op);
+ return matmulOp && MatmulTransposeBOp::isDefaultIndexingMaps(
+ matmulOp.getIndexingMapsAttr());
}
SmallVector<AffineMap>
@@ -4404,9 +4418,9 @@ BatchMatmulTransposeAOp::create(OpBuilder &builder, Location location,
}
bool BatchMatmulTransposeAOp::classof(Operation *op) {
- return dyn_cast_or_null<linalg::BatchMatmulOp>(op) &&
- BatchMatmulTransposeAOp::isDefaultIndexingMaps(
- op->getAttr("indexing_maps"));
+ auto matmulOp = dyn_cast_or_null<linalg::BatchMatmulOp>(op);
+ return matmulOp && BatchMatmulTransposeAOp::isDefaultIndexingMaps(
+ matmulOp.getIndexingMapsAttr());
}
SmallVector<AffineMap>
@@ -4497,9 +4511,9 @@ BatchMatmulTransposeBOp::create(OpBuilder &builder, Location location,
}
bool BatchMatmulTransposeBOp::classof(Operation *op) {
- return dyn_cast_or_null<linalg::BatchMatmulOp>(op) &&
- BatchMatmulTransposeBOp::isDefaultIndexingMaps(
- op->getAttr("indexing_maps"));
+ auto matmulOp = dyn_cast_or_null<linalg::BatchMatmulOp>(op);
+ return matmulOp && BatchMatmulTransposeBOp::isDefaultIndexingMaps(
+ matmulOp.getIndexingMapsAttr());
}
//===----------------------------------------------------------------------===//
@@ -5553,7 +5567,7 @@ void PackOp::print(OpAsmPrinter &p) {
p << " into " << getDest();
- p.printOptionalAttrDict((*this)->getAttrs(),
+ p.printOptionalAttrDict((*this)->getDiscardableAttrDictionary(),
{"static_inner_tiles", "inner_dims_pos",
"outer_dims_perm", "operandSegmentSizes"});
@@ -6302,7 +6316,7 @@ void UnPackOp::print(OpAsmPrinter &p) {
p << " into " << getDest();
- p.printOptionalAttrDict((*this)->getAttrs(),
+ p.printOptionalAttrDict((*this)->getDiscardableAttrDictionary(),
{"static_inner_tiles", "inner_dims_pos",
"outer_dims_perm", "operandSegmentSizes"});
diff --git a/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp b/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
index af50aa79bd491..8299e1c2edb41 100644
--- a/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
+++ b/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
@@ -1680,9 +1680,13 @@ transform::MatchOp::apply(transform::TransformRewriter &rewriter,
if (attr.getName() == getInterfaceAttrName() ||
attr.getName() == getOpsAttrName())
continue;
- if (!op->hasAttr(attr.getName()))
+ std::optional<Attribute> inherent = op->getInherentAttr(attr.getName());
+ Attribute actual = inherent.has_value()
+ ? *inherent
+ : op->getDiscardableAttr(attr.getName());
+ if (!actual)
return;
- if (op->getAttr(attr.getName()) != attr.getValue())
+ if (actual != attr.getValue())
return;
}
}
@@ -3118,8 +3122,11 @@ void SplitOp::print(OpAsmPrinter &printer) {
else
printer << getDynamicChunkSizes();
printer << " ";
- printer.printOptionalAttrDict(getOperation()->getAttrs(),
- {getStaticChunkSizesAttrName()});
+ NamedAttrList attrs(getOperation()->getDiscardableAttrDictionary());
+ attrs.append(getDimensionAttrName(), getDimensionAttr());
+ if (UnitAttr multiway = getMultiwayAttr())
+ attrs.append(getMultiwayAttrName(), multiway);
+ printer.printOptionalAttrDict(attrs, {getStaticChunkSizesAttrName()});
printer << " : " << getTarget().getType();
if (staticChunkSize == ShapedType::kDynamic)
printer << ", " << getDynamicChunkSizes().getType();
diff --git a/mlir/lib/Dialect/Linalg/Transforms/BufferizableOpInterfaceImpl.cpp b/mlir/lib/Dialect/Linalg/Transforms/BufferizableOpInterfaceImpl.cpp
index ca5ee62e5ffeb..28945642da099 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/BufferizableOpInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/BufferizableOpInterfaceImpl.cpp
@@ -74,10 +74,10 @@ static LogicalResult bufferizeDestinationStyleOpInterface(
// new op. Since the new op does not have any tensor results, it does not
// return anything.
assert(op->getNumRegions() == 1 && "expected that op has 1 region");
- OperationState opState(op->getLoc(), op->getName(), newOperands, TypeRange{},
- op->getAttrs());
- opState.addRegion();
- Operation *newOp = Operation::create(opState);
+ Operation *newOp = Operation::create(
+ op->getLoc(), op->getName(), TypeRange{}, newOperands,
+ op->getDiscardableAttrDictionary(), op->getPropertiesStorage(),
+ /*successors=*/{}, /*numRegions=*/1);
newOp->getRegion(0).getBlocks().splice(newOp->getRegion(0).begin(),
op->getRegion(0).getBlocks());
@@ -226,7 +226,8 @@ struct PackOpInterface
llvm::append_range(operands, packOp.getInnerTiles());
linalg::PackOp::create(rewriter, packOp.getLoc(), TypeRange{}, operands,
- op->getAttrs());
+ packOp.getProperties(),
+ packOp->getDiscardableAttrDictionary().getValue());
replaceOpWithBufferizedValues(rewriter, op, *destBuffer);
return success();
}
@@ -263,8 +264,10 @@ struct UnPackOpInterface
operands.push_back(*destBuffer);
llvm::append_range(operands, unPackOp.getInnerTiles());
- linalg::UnPackOp::create(rewriter, unPackOp.getLoc(), TypeRange{}, operands,
- op->getAttrs());
+ linalg::UnPackOp::create(
+ rewriter, unPackOp.getLoc(), TypeRange{}, operands,
+ unPackOp.getProperties(),
+ unPackOp->getDiscardableAttrDictionary().getValue());
replaceOpWithBufferizedValues(rewriter, op, *destBuffer);
return success();
}
diff --git a/mlir/lib/Dialect/Linalg/Transforms/DropUnitDims.cpp b/mlir/lib/Dialect/Linalg/Transforms/DropUnitDims.cpp
index c02413bd05d08..dac2891ce65e5 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/DropUnitDims.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/DropUnitDims.cpp
@@ -988,14 +988,28 @@ struct RankReduceContractionOps : OpRewritePattern<FromOpTy> {
SmallVector<Type, 1> collapsedResultTy;
if (isa<RankedTensorType>(collapsedInit.getType()))
collapsedResultTy.push_back(collapsedInit.getType());
- auto collapsedOp = ToOpTy::create(rewriter, loc, collapsedResultTy,
- ValueRange{collapsedLhs, collapsedRhs},
- ValueRange{collapsedInit});
- for (auto attr : contractionOp->getAttrs()) {
+ ToOpTy collapsedOp;
+ if constexpr (std::is_same_v<FromOpTy, BatchMatmulOp> &&
+ std::is_same_v<ToOpTy, MatmulOp>) {
+ if (TypeFnAttr castAttr = contractionOp.getCastAttr()) {
+ collapsedOp = ToOpTy::create(rewriter, loc, collapsedResultTy,
+ ValueRange{collapsedLhs, collapsedRhs},
+ ValueRange{collapsedInit}, castAttr);
+ } else {
+ collapsedOp = ToOpTy::create(rewriter, loc, collapsedResultTy,
+ ValueRange{collapsedLhs, collapsedRhs},
+ ValueRange{collapsedInit});
+ }
+ } else {
+ collapsedOp = ToOpTy::create(rewriter, loc, collapsedResultTy,
+ ValueRange{collapsedLhs, collapsedRhs},
+ ValueRange{collapsedInit});
+ }
+ for (auto attr : contractionOp->getDiscardableAttrDictionary()) {
if (attr.getName() == LinalgDialect::kMemoizedIndexingMapsAttrName ||
attr.getName() == "indexing_maps")
continue;
- collapsedOp->setAttr(attr.getName(), attr.getValue());
+ collapsedOp->setDiscardableAttr(attr.getName(), attr.getValue());
}
auto results = contractionOp.getResults();
diff --git a/mlir/lib/Dialect/Linalg/Transforms/ElementwiseToLinalg.cpp b/mlir/lib/Dialect/Linalg/Transforms/ElementwiseToLinalg.cpp
index aea17d8de4a76..1338ca0aeb79b 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/ElementwiseToLinalg.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/ElementwiseToLinalg.cpp
@@ -142,10 +142,11 @@ struct ConvertAnyElementwiseMappableOpOnRankedTensors : public RewritePattern {
llvm::map_to_vector<6>(op->getResultTypes(), [](Type type) {
return cast<TensorType>(type).getElementType();
});
- Operation *scalarOp =
- builder.create(loc, op->getName().getIdentifier(),
- regionArgs.take_front(op->getNumOperands()),
- resultEltTys, op->getAttrs());
+ Operation *scalarOp = builder.insert(Operation::create(
+ loc, op->getName(), resultEltTys,
+ regionArgs.take_front(op->getNumOperands()),
+ op->getDiscardableAttrDictionary(), op->getPropertiesStorage(),
+ /*successors=*/{}, /*numRegions=*/0));
linalg::YieldOp::create(builder, loc, scalarOp->getResults());
});
return success();
diff --git a/mlir/lib/Dialect/Linalg/Transforms/EraseUnusedOperandsAndResults.cpp b/mlir/lib/Dialect/Linalg/Transforms/EraseUnusedOperandsAndResults.cpp
index 6800b3042d524..506e20ab436f8 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/EraseUnusedOperandsAndResults.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/EraseUnusedOperandsAndResults.cpp
@@ -271,9 +271,9 @@ mlir::linalg::deduplicateOperandsAndRemoveDeadResults(
});
// Copy over unknown attributes. They might be load bearing for some flow.
ArrayRef<StringRef> odsAttrs = genericOp.getAttributeNames();
- for (NamedAttribute kv : genericOp->getAttrs())
+ for (NamedAttribute kv : genericOp->getDiscardableAttrDictionary())
if (!llvm::is_contained(odsAttrs, kv.getName().getValue()))
- newOp->setAttr(kv.getName(), kv.getValue());
+ newOp->setDiscardableAttr(kv.getName(), kv.getValue());
// Fix up the payload of the canonicalized operation.
populateOpPayload(genericOp, newOp, origInsToNewInsPos, origOutsToNewOutsPos,
diff --git a/mlir/lib/Dialect/Linalg/Transforms/FoldIntoElementwise.cpp b/mlir/lib/Dialect/Linalg/Transforms/FoldIntoElementwise.cpp
index 94db259d662d4..bbc6d3968b00c 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/FoldIntoElementwise.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/FoldIntoElementwise.cpp
@@ -93,7 +93,8 @@ struct FoldIntoElementwisePattern : public OpInterfaceRewritePattern<LinalgOp> {
rewriter.modifyOpInPlace(op, [&] {
for (auto [index, operand] : llvm::enumerate(op.getDpsInputOperands()))
op->setOperand(operand->getOperandNumber(), newIns[index]);
- op->setAttr("indexing_maps", rewriter.getAffineMapArrayAttr(newMaps));
+ op->setInherentAttr(rewriter.getStringAttr("indexing_maps"),
+ rewriter.getAffineMapArrayAttr(newMaps));
});
return success();
}
diff --git a/mlir/lib/Dialect/Linalg/Transforms/SimplifyDepthwiseConv.cpp b/mlir/lib/Dialect/Linalg/Transforms/SimplifyDepthwiseConv.cpp
index c55a0bf7ef9a3..c6a305d539c10 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/SimplifyDepthwiseConv.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/SimplifyDepthwiseConv.cpp
@@ -93,7 +93,7 @@ matchAndReplaceDepthwiseConv(Operation *operation, Value input, Value kernel,
if (!newConv)
return failure();
for (auto attr : preservedAttrs)
- newConv->setAttr(attr.getName(), attr.getValue());
+ newConv->setDiscardableAttr(attr.getName(), attr.getValue());
// Expand dimensions back out to
rewriter.replaceOpWithNewOp<tensor::ExpandShapeOp>(
diff --git a/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp b/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp
index b00ab8a7d6ee7..c84e5e50cb0e2 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp
@@ -1149,8 +1149,10 @@ struct PackOpTiling
for (auto tile : packOp.getInnerTiles())
tiledOperands.push_back(tile);
- Operation *tiledPackOp = PackOp::create(
- b, loc, TypeRange{outSlice.getType()}, tiledOperands, op->getAttrs());
+ PackOp tiledPackOp =
+ PackOp::create(b, loc, TypeRange{outSlice.getType()}, tiledOperands,
+ packOp.getProperties(),
+ packOp->getDiscardableAttrDictionary().getValue());
return TilingResult{
{tiledPackOp},
@@ -1486,8 +1488,10 @@ struct PackOpTiling
for (auto tile : packOp.getInnerTiles())
tiledOperands.push_back(tile);
- Operation *tiledPackOp = PackOp::create(
- b, loc, TypeRange{outSlice.getType()}, tiledOperands, op->getAttrs());
+ PackOp tiledPackOp =
+ PackOp::create(b, loc, TypeRange{outSlice.getType()}, tiledOperands,
+ packOp.getProperties(),
+ packOp->getDiscardableAttrDictionary().getValue());
return TilingResult{
{tiledPackOp},
@@ -1727,8 +1731,10 @@ struct UnPackOpTiling
for (auto tile : unpackOp.getInnerTiles())
tiledOperands.push_back(tile);
- Operation *tiledUnpackOp = UnPackOp::create(
- b, loc, TypeRange{sliceDest.getType()}, tiledOperands, op->getAttrs());
+ UnPackOp tiledUnpackOp =
+ UnPackOp::create(b, loc, TypeRange{sliceDest.getType()}, tiledOperands,
+ unpackOp.getProperties(),
+ unpackOp->getDiscardableAttrDictionary().getValue());
if (isPerfectTilingCase)
return TilingResult{{tiledUnpackOp},
@@ -1986,9 +1992,10 @@ struct UnPackOpTiling
tiledOperands.push_back(tile);
// Create tiled unpack op.
- Operation *tiledUnPackOp =
+ UnPackOp tiledUnPackOp =
UnPackOp::create(b, loc, TypeRange{extractDestSlice.getType()},
- tiledOperands, op->getAttrs());
+ tiledOperands, unPackOp.getProperties(),
+ unPackOp->getDiscardableAttrDictionary().getValue());
return TilingResult{{tiledUnPackOp},
SmallVector<Value>(tiledUnPackOp->getResults()),
diff --git a/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp b/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp
index 21ca3108efcd6..e8f8d737e86de 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp
@@ -1442,10 +1442,12 @@ vectorizeOneOp(RewriterBase &rewriter, VectorizationState &state,
: resultType);
}
// d. Build and return the new op.
- return VectorizationHookResult{
- VectorizationHookStatus::NewOp,
- rewriter.create(op->getLoc(), op->getName().getIdentifier(), vecOperands,
- resultTypes, op->getAttrs())};
+ Operation *newOp = Operation::create(
+ op->getLoc(), op->getName(), resultTypes, vecOperands,
+ op->getDiscardableAttrDictionary(), op->getPropertiesStorage(),
+ /*successors=*/{}, /*numRegions=*/0);
+ return VectorizationHookResult{VectorizationHookStatus::NewOp,
+ rewriter.insert(newOp)};
}
/// Generic vectorization function that rewrites the body of a `linalgOp` into
@@ -2733,8 +2735,8 @@ struct PadOpVectorizationWithTransferReadPattern
rewriter.modifyOpInPlace(xferOp, [&]() {
SmallVector<bool> inBounds(xferOp.getVectorType().getRank(), false);
- xferOp->setAttr(xferOp.getInBoundsAttrName(),
- rewriter.getBoolArrayAttr(inBounds));
+ xferOp->setInherentAttr(xferOp.getInBoundsAttrName(),
+ rewriter.getBoolArrayAttr(inBounds));
xferOp.getBaseMutable().assign(padOp.getSource());
xferOp.getPaddingMutable().assign(padValue);
});
@@ -3794,8 +3796,9 @@ struct Conv1DGenerator
SmallVector<bool> inBounds(maskShape.size(), true);
auto xferOp = cast<VectorTransferOpInterface>(opToMask);
- xferOp->setAttr(xferOp.getInBoundsAttrName(),
- rewriter.getBoolArrayAttr(inBounds));
+ xferOp->setInherentAttr(
+ rewriter.getStringAttr(xferOp.getInBoundsAttrName()),
+ rewriter.getBoolArrayAttr(inBounds));
SmallVector<OpFoldResult> mixedDims = vector::getMixedSizesXfer(
cast<LinalgOp>(op).hasPureTensorSemantics(), opToMask, rewriter);
diff --git a/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp b/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp
index c8bba20fc7edf..c6a2d1e97f644 100644
--- a/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp
+++ b/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp
@@ -162,7 +162,7 @@ bubbleDownCastsPassthroughOpImpl(ConcreteOpTy op, OpBuilder &builder,
// Create the new op and results.
auto newOp = ConcreteOpTy::create(
builder, op.getLoc(), TypeRange(resTy), operands, op.getProperties(),
- llvm::to_vector_of<NamedAttribute>(op->getDiscardableAttrs()));
+ op->getDiscardableAttrDictionary().getValue());
// Insert a memory-space cast to the original memory space of the op.
MemorySpaceCastOpInterface result = castOp.cloneMemorySpaceCastOp(
@@ -377,7 +377,7 @@ void AllocaScopeOp::print(OpAsmPrinter &p) {
p.printRegion(getBodyRegion(),
/*printEntryBlockArgs=*/false,
/*printBlockTerminators=*/printBlockTerminators);
- p.printOptionalAttrDict((*this)->getAttrs());
+ p.printOptionalAttrDict((*this)->getDiscardableAttrDictionary());
}
ParseResult AllocaScopeOp::parse(OpAsmParser &parser, OperationState &result) {
@@ -1262,7 +1262,7 @@ void DmaStartOp::print(OpAsmPrinter &p) {
if (isStrided())
p << ", " << getStride() << ", " << getNumElementsPerStride();
- p.printOptionalAttrDict((*this)->getAttrs());
+ p.printOptionalAttrDict((*this)->getDiscardableAttrDictionary());
p << " : " << getSrcMemRef().getType() << ", " << getDstMemRef().getType()
<< ", " << getTagMemRef().getType();
}
@@ -1652,7 +1652,7 @@ void GenericAtomicRMWOp::print(OpAsmPrinter &p) {
p << ' ' << getMemref() << "[" << getIndices()
<< "] : " << getMemref().getType() << ' ';
p.printRegion(getRegion());
- p.printOptionalAttrDict((*this)->getAttrs());
+ p.printOptionalAttrDict((*this)->getDiscardableAttrDictionary());
}
TypedValue<MemRefType> GenericAtomicRMWOp::getAccessedMemref() {
@@ -1941,7 +1941,7 @@ void PrefetchOp::print(OpAsmPrinter &p) {
p << ", locality<" << getLocalityHint();
p << ">, " << (getIsDataCache() ? "data" : "instr");
p.printOptionalAttrDict(
- (*this)->getAttrs(),
+ (*this)->getDiscardableAttrDictionary(),
/*elidedAttrs=*/{"localityHint", "isWrite", "isDataCache"});
p << " : " << getMemRefType();
}
@@ -3837,7 +3837,8 @@ void TransposeOp::build(OpBuilder &b, OperationState &result, Value in,
// transpose $in $permutation attr-dict : type($in) `to` type(results)
void TransposeOp::print(OpAsmPrinter &p) {
p << " " << getIn() << " " << getPermutation();
- p.printOptionalAttrDict((*this)->getAttrs(), {getPermutationAttrStrName()});
+ p.printOptionalAttrDict((*this)->getDiscardableAttrDictionary(),
+ {getPermutationAttrStrName()});
p << " : " << getIn().getType() << " to " << getType();
}
diff --git a/mlir/lib/Dialect/MemRef/Transforms/AllocationOpInterfaceImpl.cpp b/mlir/lib/Dialect/MemRef/Transforms/AllocationOpInterfaceImpl.cpp
index 75cc39e61656a..b53e3bdf1cf69 100644
--- a/mlir/lib/Dialect/MemRef/Transforms/AllocationOpInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/MemRef/Transforms/AllocationOpInterfaceImpl.cpp
@@ -34,11 +34,12 @@ struct DefaultAllocationInterface
}
static ::std::optional<::mlir::Operation *>
buildPromotedAlloc(OpBuilder &builder, Value alloc) {
- Operation *definingOp = alloc.getDefiningOp();
- return memref::AllocaOp::create(
- builder, definingOp->getLoc(),
- cast<MemRefType>(definingOp->getResultTypes()[0]),
- definingOp->getOperands(), definingOp->getAttrs());
+ auto allocOp = cast<memref::AllocOp>(alloc.getDefiningOp());
+ memref::AllocaOp allocaOp = memref::AllocaOp::create(
+ builder, allocOp.getLoc(), allocOp.getType(), allocOp.getDynamicSizes(),
+ allocOp.getSymbolOperands(), allocOp.getAlignmentAttr());
+ allocaOp->setDiscardableAttrs(allocOp->getDiscardableAttrDictionary());
+ return allocaOp.getOperation();
}
};
diff --git a/mlir/lib/Dialect/MemRef/Transforms/MultiBuffer.cpp b/mlir/lib/Dialect/MemRef/Transforms/MultiBuffer.cpp
index ce45f847ccaed..69adf0611b623 100644
--- a/mlir/lib/Dialect/MemRef/Transforms/MultiBuffer.cpp
+++ b/mlir/lib/Dialect/MemRef/Transforms/MultiBuffer.cpp
@@ -224,8 +224,9 @@ mlir::memref::multiBuffer(RewriterBase &rewriter, memref::AllocOp allocOp,
Location loc = allocOp->getLoc();
OpBuilder::InsertionGuard g(rewriter);
rewriter.setInsertionPoint(allocOp);
- auto mbAlloc = memref::AllocOp::create(rewriter, loc, mbMemRefType,
- ValueRange{}, allocOp->getAttrs());
+ auto mbAlloc = memref::AllocOp::create(
+ rewriter, loc, mbMemRefType, ValueRange{}, allocOp.getAlignmentAttr());
+ mbAlloc->setDiscardableAttrs(allocOp->getDiscardableAttrDictionary());
LLVM_DEBUG(DBGS() << "--multi-buffered alloc: " << mbAlloc << "\n");
// 3. Within the loop, build the modular leading index (i.e. each loop
diff --git a/mlir/lib/Dialect/MemRef/Transforms/NormalizeMemRefs.cpp b/mlir/lib/Dialect/MemRef/Transforms/NormalizeMemRefs.cpp
index d5e0dace3c775..d1ca18e7661e5 100644
--- a/mlir/lib/Dialect/MemRef/Transforms/NormalizeMemRefs.cpp
+++ b/mlir/lib/Dialect/MemRef/Transforms/NormalizeMemRefs.cpp
@@ -462,6 +462,9 @@ void NormalizeMemRefs::normalizeFuncOpMemRefs(func::FuncOp funcOp,
}
}
if (!replacingMemRefUsesFailed) {
+ for (auto [oldRegion, newRegion] :
+ llvm::zip(op->getRegions(), newOp->getRegions()))
+ newRegion.takeBody(oldRegion);
// Replace other ops with new op and delete the old op when the
// replacement succeeded.
op->replaceAllUsesWith(newOp);
@@ -510,12 +513,7 @@ void NormalizeMemRefs::normalizeFuncOpMemRefs(func::FuncOp funcOp,
/// without affine map, `oldOp` is returned without modification.
Operation *NormalizeMemRefs::createOpResultsNormalized(func::FuncOp funcOp,
Operation *oldOp) {
- // Prepare OperationState to create newOp containing normalized memref in
- // the operation results.
- OperationState result(oldOp->getLoc(), oldOp->getName());
- result.addOperands(oldOp->getOperands());
- result.addAttributes(oldOp->getAttrs());
- // Add normalized MemRefType to the OperationState.
+ // Compute the normalized result types for the new operation.
SmallVector<Type, 4> resultTypes;
OpBuilder b(funcOp);
bool resultTypeNormalized = false;
@@ -539,16 +537,15 @@ Operation *NormalizeMemRefs::createOpResultsNormalized(func::FuncOp funcOp,
resultTypes.push_back(newMemRefType);
resultTypeNormalized = true;
}
- result.addTypes(resultTypes);
// When all of the results of `oldOp` have no memrefs or memrefs without
// affine map, `oldOp` is returned without modification.
if (resultTypeNormalized) {
OpBuilder bb(oldOp);
- for (auto &oldRegion : oldOp->getRegions()) {
- Region *newRegion = result.addRegion();
- newRegion->takeBody(oldRegion);
- }
- return bb.create(result);
+ Operation *newOp = Operation::create(
+ oldOp->getLoc(), oldOp->getName(), resultTypes, oldOp->getOperands(),
+ oldOp->getDiscardableAttrDictionary(), oldOp->getPropertiesStorage(),
+ /*successors=*/{}, oldOp->getNumRegions());
+ return bb.insert(newOp);
}
return oldOp;
}
diff --git a/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir b/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir
index 325a00566845f..d20f06fd3278a 100644
--- a/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir
+++ b/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir
@@ -1,5 +1,6 @@
// Note: Default is function-boundary-type-conversion=infer-layout-map
// RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries=1" -canonicalize -drop-equivalent-buffer-results -split-input-file | FileCheck %s
+// RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries=1" -split-input-file | FileCheck %s --check-prefix=INHERENT
// Run fuzzer with
diff erent seeds.
// RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries=1 test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=23" -split-input-file -o /dev/null
@@ -590,6 +591,7 @@ func.func private @inner_func(%t: tensor<?xf32>) -> tensor<?xf32> {
// CHECK-LABEL: func @equivalent_func_arg(
// CHECK-SAME: %[[arg0:.*]]: memref<?xf32
+// INHERENT-LABEL: func @equivalent_func_arg(
func.func @equivalent_func_arg(%t0: tensor<?xf32> {bufferization.writable = true},
%c0: index, %c10: index, %c1: index) -> tensor<?xf32> {
// CHECK-NOT: alloc
@@ -597,7 +599,8 @@ func.func @equivalent_func_arg(%t0: tensor<?xf32> {bufferization.writable = true
// CHECK: scf.for {{.*}} iter_args(%[[t1:.*]] = %[[arg0]])
%1 = scf.for %iv = %c0 to %c10 step %c1 iter_args(%t1 = %t0) -> (tensor<?xf32>) {
// CHECK: call @inner_func(%[[t1]])
- %3 = func.call @inner_func(%t1) : (tensor<?xf32>) -> tensor<?xf32>
+ // INHERENT: call @inner_func({{.*}}) {no_inline}
+ %3 = func.call @inner_func(%t1) {no_inline} : (tensor<?xf32>) -> tensor<?xf32>
// CHECK: scf.yield %[[t1]]
scf.yield %3 : tensor<?xf32>
}
diff --git a/mlir/test/Dialect/Linalg/library-calls.mlir b/mlir/test/Dialect/Linalg/library-calls.mlir
index 77c9d4a911447..e7ae43ed1bdc8 100644
--- a/mlir/test/Dialect/Linalg/library-calls.mlir
+++ b/mlir/test/Dialect/Linalg/library-calls.mlir
@@ -17,7 +17,8 @@ func.func @matmul(%A: memref<?x?xf32>, %B: memref<?x?xf32>) -> (memref<?x?xf32>)
linalg.fill ins(%f0 : f32) outs(%C : memref<?x?xf32>)
// CHECK: call @linalg_matmul_viewsxsxf32_viewsxsxf32_viewsxsxf32({{.*}}) : (memref<?x?xf32, {{.*}}>, memref<?x?xf32, {{.*}}>, memref<?x?xf32, {{.*}}>) -> ()
- linalg.matmul ins(%A, %B: memref<?x?xf32>, memref<?x?xf32>)
+ linalg.matmul {metadata = #linalg.binary_fn<add>}
+ ins(%A, %B: memref<?x?xf32>, memref<?x?xf32>)
outs(%C: memref<?x?xf32>)
return %C : memref<?x?xf32>
}
diff --git a/mlir/test/Dialect/Linalg/rank-reduce-contraction-ops.mlir b/mlir/test/Dialect/Linalg/rank-reduce-contraction-ops.mlir
index 704576de41960..b7c095ca96b2d 100644
--- a/mlir/test/Dialect/Linalg/rank-reduce-contraction-ops.mlir
+++ b/mlir/test/Dialect/Linalg/rank-reduce-contraction-ops.mlir
@@ -18,6 +18,19 @@ func.func @singleton_batch_matmul_tensor(%arg0 : tensor<1x128x512xf32>, %arg1 :
// -----
+func.func @singleton_batch_matmul_unsigned_cast(
+ %arg0: tensor<1x128x512xi16>, %arg1: tensor<1x512x256xi64>,
+ %arg2: tensor<1x128x256xi32>) -> tensor<1x128x256xi32> {
+ // CHECK-LABEL: @singleton_batch_matmul_unsigned_cast
+ // CHECK: linalg.matmul {cast = #linalg.type_fn<cast_unsigned>}
+ %0 = linalg.batch_matmul {cast = #linalg.type_fn<cast_unsigned>}
+ ins(%arg0, %arg1 : tensor<1x128x512xi16>, tensor<1x512x256xi64>)
+ outs(%arg2 : tensor<1x128x256xi32>) -> tensor<1x128x256xi32>
+ return %0 : tensor<1x128x256xi32>
+}
+
+// -----
+
func.func @singleton_batch_matmul_memref(%arg0 : memref<1x?x?xf32>, %arg1 : memref<1x?x?xf32>, %arg2: memref<1x?x?xf32>) {
// CHECK-LABEL: @singleton_batch_matmul_memref
// CHECK-SAME: %[[LHS:[a-zA-Z0-9]+]]: memref<1x?x?xf32>
diff --git a/mlir/test/Dialect/MemRef/multibuffer.mlir b/mlir/test/Dialect/MemRef/multibuffer.mlir
index b004ebfa1abd0..948a60aaac25d 100644
--- a/mlir/test/Dialect/MemRef/multibuffer.mlir
+++ b/mlir/test/Dialect/MemRef/multibuffer.mlir
@@ -4,10 +4,10 @@
// CHECK-LABEL: func @multi_buffer
func.func @multi_buffer(%a: memref<1024x1024xf32>) {
-// CHECK-DAG: %[[A:.*]] = memref.alloc() {someAttribute} : memref<5x4x128xf32>
+// CHECK-DAG: %[[A:.*]] = memref.alloc() alignment = 64 {someAttribute} : memref<5x4x128xf32>
// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
// CHECK-DAG: %[[C3:.*]] = arith.constant 3 : index
- %0 = memref.alloc() {someAttribute} : memref<4x128xf32>
+ %0 = memref.alloc() alignment = 64 {someAttribute} : memref<4x128xf32>
%c1024 = arith.constant 1024 : index
%c1 = arith.constant 1 : index
%c3 = arith.constant 3 : index
diff --git a/mlir/test/lib/Dialect/Bufferization/TestTensorLikeAndBufferLike.cpp b/mlir/test/lib/Dialect/Bufferization/TestTensorLikeAndBufferLike.cpp
index 60e60849f3e6c..3e71175a34474 100644
--- a/mlir/test/lib/Dialect/Bufferization/TestTensorLikeAndBufferLike.cpp
+++ b/mlir/test/lib/Dialect/Bufferization/TestTensorLikeAndBufferLike.cpp
@@ -85,7 +85,7 @@ struct TestTensorLikeAndBufferLikePass
op.walk([](func::FuncOp funcOp) {
const auto dict = findAllImplementeesOfTensorOrBufferLike(funcOp);
if (!dict.empty()) {
- funcOp->setAttr("found", dict);
+ funcOp->setDiscardableAttr("found", dict);
}
});
}
diff --git a/mlir/test/mlir-linalg-ods-gen/test-linalg-ods-yaml-gen.yaml b/mlir/test/mlir-linalg-ods-gen/test-linalg-ods-yaml-gen.yaml
index 00c70705cbb35..e2c811d523da2 100644
--- a/mlir/test/mlir-linalg-ods-gen/test-linalg-ods-yaml-gen.yaml
+++ b/mlir/test/mlir-linalg-ods-gen/test-linalg-ods-yaml-gen.yaml
@@ -183,7 +183,7 @@ structured_op: !LinalgStructuredOpConfig
# IMPL: Test2Op::hasDynamicIndexingMaps() { return true; }
# IMPL: Test2Op::verifyIndexingMapRequiredAttributes()
-# IMPL: auto attr = op->getAttrOfType<DenseElementsAttr>("strides")
+# IMPL: op->getInherentAttrOfType<DenseElementsAttr>("strides")
# IMPL: "incorrect element type for index attribute 'strides'"
# IMPL: "incorrect shape for index attribute 'strides'"
# IMPL: void Test2Op::regionBuilder(ImplicitLocOpBuilder &b,
diff --git a/mlir/tools/mlir-linalg-ods-gen/mlir-linalg-ods-yaml-gen.cpp b/mlir/tools/mlir-linalg-ods-gen/mlir-linalg-ods-yaml-gen.cpp
index 67dbab8ca79f9..c84efc50caa68 100644
--- a/mlir/tools/mlir-linalg-ods-gen/mlir-linalg-ods-yaml-gen.cpp
+++ b/mlir/tools/mlir-linalg-ods-gen/mlir-linalg-ods-yaml-gen.cpp
@@ -623,7 +623,8 @@ SmallVector<utils::IteratorType> {0}::getIteratorTypesArray() {{
static const char structuredOpIndexingMapsFormat[] = R"FMT(
ArrayAttr {0}::getIndexingMaps() {{
static const char memoizeAttr[] = "linalg.memoized_indexing_maps";
- ArrayAttr cached = getOperation()->getAttrOfType<ArrayAttr>(memoizeAttr);
+ ArrayAttr cached =
+ getOperation()->getDiscardableAttrOfType<ArrayAttr>(memoizeAttr);
if (cached)
return cached;
@@ -632,7 +633,7 @@ ArrayAttr {0}::getIndexingMaps() {{
SmallVector<AffineMap> maps;
{1}
cached = Builder(context).getAffineMapArrayAttr(maps);
- getOperation()->setAttr(memoizeAttr, cached);
+ getOperation()->setDiscardableAttr(memoizeAttr, cached);
return cached;
}
)FMT";
@@ -976,7 +977,7 @@ std::string {0}::getLibraryCallName() {{
// {0}: Attribute name
// {1}: Attribute size
static const char attrFmt[] = R"FMT(
-if (auto attr = op->getAttrOfType<DenseElementsAttr>("{0}")) {{
+if (auto attr = op->getInherentAttrOfType<DenseElementsAttr>("{0}")) {{
if (!attr.getType().getElementType().isInteger(64))
return op->emitError("incorrect element type for index attribute '{0}'");
if (attr.getType().getShape() != ArrayRef<int64_t>{{ {1} })
diff --git a/mlir/unittests/Dialect/Linalg/InferConvolutionDimsTest.cpp b/mlir/unittests/Dialect/Linalg/InferConvolutionDimsTest.cpp
index cab17f2a6e9c1..558becad8f04c 100644
--- a/mlir/unittests/Dialect/Linalg/InferConvolutionDimsTest.cpp
+++ b/mlir/unittests/Dialect/Linalg/InferConvolutionDimsTest.cpp
@@ -156,6 +156,8 @@ TEST_F(InferConvolutionDimsTest, Conv2DPairing) {
// Create equivalent generic with swapped filter loop order: (oh, ow, kw, kh)
linalg::GenericOp swappedOp =
createConv2DWithSwappedFilterLoops(builder, conv2DOp);
+ swappedOp->setDiscardableAttr("strides", builder.getI64TensorAttr({7, 8}));
+ swappedOp->setDiscardableAttr("dilations", builder.getI64TensorAttr({9, 10}));
FailureOr<ConvolutionDimensions> swappedDims =
inferConvolutionDims(swappedOp);
ASSERT_TRUE(succeeded(swappedDims));
@@ -174,6 +176,8 @@ TEST_F(InferConvolutionDimsTest, Conv2DPairing) {
<< "outputImage[0]=0 should pair with filterLoop[0]=3 (oh <-> kh)";
EXPECT_EQ(swappedDims->filterLoop[1], 2u)
<< "outputImage[1]=1 should pair with filterLoop[1]=2 (ow <-> kw)";
+ EXPECT_EQ(swappedDims->strides, (SmallVector<int64_t, 2>{1, 1}));
+ EXPECT_EQ(swappedDims->dilations, (SmallVector<int64_t, 2>{1, 1}));
}
/// Asserts that two ConvolutionDimensions are equal across every populated
@@ -228,6 +232,10 @@ TEST_F(InferConvolutionDimsTest, MapsOverloadMatchesOpOverload) {
FailureOr<ConvolutionDimensions> fromOp = inferConvolutionDims(linalgOp);
ASSERT_TRUE(succeeded(fromOp))
<< "op overload failed for " << op->getName().getStringRef().str();
+ if (op == convs.front()) {
+ EXPECT_EQ(fromOp->strides, SmallVector<int64_t>({2, 1}));
+ EXPECT_EQ(fromOp->dilations, SmallVector<int64_t>({3, 1}));
+ }
FailureOr<ConvolutionDimensions> fromMaps =
inferConvolutionDims(linalgOp.getIndexingMapsArray());
ASSERT_TRUE(succeeded(fromMaps))
diff --git a/mlir/unittests/IR/OperationSupportTest.cpp b/mlir/unittests/IR/OperationSupportTest.cpp
index fa5fdfe16fde0..33f69a6e8f21a 100644
--- a/mlir/unittests/IR/OperationSupportTest.cpp
+++ b/mlir/unittests/IR/OperationSupportTest.cpp
@@ -307,6 +307,11 @@ TEST(OperandStorageTest, PopulateDefaultAttrs) {
nullptr, nullptr, req2);
auto opt = op->getInherentAttr("default_valued_attr");
EXPECT_NE(opt, nullptr) << *op;
+ auto typed = op->getInherentAttrOfType<IntegerAttr>("default_valued_attr");
+ ASSERT_TRUE(typed) << *op;
+ EXPECT_EQ(typed.getInt(), 42);
+ EXPECT_FALSE(op->getInherentAttrOfType<StringAttr>("default_valued_attr"));
+ EXPECT_FALSE(op->getInherentAttrOfType<IntegerAttr>("unknown_attr"));
op->destroy();
}
More information about the Mlir-commits
mailing list