[Mlir-commits] [mlir] [mlir][Analysis] Use explicit attribute APIs to distinguish between inherent/discardable attrs (PR #218878)
Mehdi Amini
llvmlistbot at llvm.org
Wed Aug 26 03:26:31 PDT 2026
https://github.com/joker-eph created https://github.com/llvm/llvm-project/pull/218878
Migrate analysis implementations and test utilities to explicit discardable or inherent operation attribute access.
Assisted-by: Codex
>From 5c2904dc49a9b2ef5c8d5fa5bd121c4c3afb7f5c Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Thu, 20 Aug 2026 07:30:04 -0700
Subject: [PATCH] [mlir][Analysis] Use explicit attribute APIs
Migrate analysis implementations and test utilities to explicit
discardable or inherent operation attribute access.
Assisted-by: Codex
---
mlir/lib/Analysis/CallGraph.cpp | 15 ++++++++++++---
.../DataFlow/ConstantPropagationAnalysis.cpp | 8 ++++++--
.../Analysis/DataFlow/TestDeadCodeAnalysis.cpp | 2 +-
.../TestDenseBackwardDataFlowAnalysis.cpp | 13 +++++++------
.../Analysis/DataFlow/TestDenseDataFlowAnalysis.h | 2 +-
.../DataFlow/TestDenseForwardDataFlowAnalysis.cpp | 5 +++--
.../DataFlow/TestIntegerDivisibilityAnalysis.cpp | 5 +++--
.../Analysis/DataFlow/TestLivenessAnalysis.cpp | 2 +-
.../TestSparseBackwardDataFlowAnalysis.cpp | 6 +++---
mlir/test/lib/Analysis/TestAliasAnalysis.cpp | 5 +++--
mlir/test/lib/Analysis/TestDataFlowFramework.cpp | 15 ++++++++-------
mlir/test/lib/Analysis/TestSlice.cpp | 4 ++--
mlir/test/lib/Analysis/TestTopologicalSort.cpp | 8 ++++----
13 files changed, 54 insertions(+), 36 deletions(-)
diff --git a/mlir/lib/Analysis/CallGraph.cpp b/mlir/lib/Analysis/CallGraph.cpp
index d6fe62d8e58d6..4098c657f63e2 100644
--- a/mlir/lib/Analysis/CallGraph.cpp
+++ b/mlir/lib/Analysis/CallGraph.cpp
@@ -195,9 +195,18 @@ void CallGraph::print(raw_ostream &os) const {
auto *parentOp = callableRegion->getParentOp();
os << "'" << callableRegion->getParentOp()->getName() << "' - Region #"
<< callableRegion->getRegionNumber();
- auto attrs = parentOp->getAttrDictionary();
- if (!attrs.empty())
- os << " : " << attrs;
+ NamedAttrList attrs(parentOp->getDiscardableAttrDictionary());
+ parentOp->getName().walkInherentAttrs(
+ parentOp,
+ [&](StringRef name, Attribute &attr) { attrs.append(name, attr); });
+ if (!attrs.empty()) {
+ os << " : { ";
+ llvm::interleaveComma(attrs, os, [&](NamedAttribute attr) {
+ os << attr.getName().getValue() << " = ";
+ attr.getValue().print(os);
+ });
+ os << " }";
+ }
};
for (auto &nodeIt : nodes) {
diff --git a/mlir/lib/Analysis/DataFlow/ConstantPropagationAnalysis.cpp b/mlir/lib/Analysis/DataFlow/ConstantPropagationAnalysis.cpp
index e6e7491b041ee..d067365a65c6c 100644
--- a/mlir/lib/Analysis/DataFlow/ConstantPropagationAnalysis.cpp
+++ b/mlir/lib/Analysis/DataFlow/ConstantPropagationAnalysis.cpp
@@ -70,7 +70,8 @@ LogicalResult SparseConstantPropagation::visitOperation(
// folds in-place. The constant passed in may not correspond to the real
// runtime value, so in-place updates are not allowed.
SmallVector<Value, 8> originalOperands(op->getOperands());
- DictionaryAttr originalAttrs = op->getAttrDictionary();
+ DictionaryAttr originalAttrs = op->getDiscardableAttrDictionary();
+ Attribute originalProperties = op->getPropertiesAsAttribute();
// Simulate the result of folding this operation to a constant.
SmallVector<OpFoldResult, 8> foldResults;
@@ -83,7 +84,10 @@ LogicalResult SparseConstantPropagation::visitOperation(
// relinks use-lists even for identical values.
if (!llvm::equal(op->getOperands(), originalOperands))
op->setOperands(originalOperands);
- op->setAttrs(originalAttrs);
+ op->setDiscardableAttrs(originalAttrs);
+ if (originalProperties)
+ (void)op->setPropertiesFromAttribute(originalProperties,
+ /*emitError=*/nullptr);
// If folding failed or was in-place, mark the results as overdefined. We
// don't allow in-place folds here: the goal is simulated execution, not
diff --git a/mlir/test/lib/Analysis/DataFlow/TestDeadCodeAnalysis.cpp b/mlir/test/lib/Analysis/DataFlow/TestDeadCodeAnalysis.cpp
index 327e807873714..4ab2a3170ef61 100644
--- a/mlir/test/lib/Analysis/DataFlow/TestDeadCodeAnalysis.cpp
+++ b/mlir/test/lib/Analysis/DataFlow/TestDeadCodeAnalysis.cpp
@@ -19,7 +19,7 @@ using namespace mlir::dataflow;
static void printAnalysisResults(DataFlowSolver &solver, Operation *op,
raw_ostream &os) {
op->walk([&](Operation *op) {
- auto tag = op->getAttrOfType<StringAttr>("tag");
+ auto tag = op->getDiscardableAttrOfType<StringAttr>("tag");
if (!tag)
return;
os << tag.getValue() << ":\n";
diff --git a/mlir/test/lib/Analysis/DataFlow/TestDenseBackwardDataFlowAnalysis.cpp b/mlir/test/lib/Analysis/DataFlow/TestDenseBackwardDataFlowAnalysis.cpp
index e1ea28c06659f..f969869b92482 100644
--- a/mlir/test/lib/Analysis/DataFlow/TestDenseBackwardDataFlowAnalysis.cpp
+++ b/mlir/test/lib/Analysis/DataFlow/TestDenseBackwardDataFlowAnalysis.cpp
@@ -320,7 +320,7 @@ struct TestNextAccessPass
innerAttrs.reserve(nextAcc->get().size());
for (Operation *nextAccOp : nextAcc->get()) {
if (auto nextAccTag =
- nextAccOp->getAttrOfType<StringAttr>(kTagAttrName)) {
+ nextAccOp->getDiscardableAttrOfType<StringAttr>(kTagAttrName)) {
innerAttrs.push_back(nextAccTag);
continue;
}
@@ -356,7 +356,7 @@ struct TestNextAccessPass
LDBG() << " Dataflow solver completed successfully";
LDBG() << " Walking operations to set next access attributes";
op->walk([&](Operation *op) {
- auto tag = op->getAttrOfType<StringAttr>(kTagAttrName);
+ auto tag = op->getDiscardableAttrOfType<StringAttr>(kTagAttrName);
if (!tag)
return;
@@ -364,8 +364,8 @@ struct TestNextAccessPass
<< OpWithFlags(op, OpPrintingFlags().skipRegions());
const NextAccess *nextAccess =
solver.lookupState<NextAccess>(solver.getProgramPointAfter(op));
- op->setAttr(kNextAccessAttrName,
- makeNextAccessAttribute(op, solver, nextAccess));
+ op->setDiscardableAttr(kNextAccessAttrName,
+ makeNextAccessAttribute(op, solver, nextAccess));
auto iface = dyn_cast<RegionBranchOpInterface>(op);
if (!iface)
@@ -383,8 +383,9 @@ struct TestNextAccessPass
entryPointNextAccess.push_back(makeNextAccessAttribute(
op, solver, solver.lookupState<NextAccess>(successorPoint)));
}
- op->setAttr(kAtEntryPointAttrName,
- ArrayAttr::get(op->getContext(), entryPointNextAccess));
+ op->setDiscardableAttr(
+ kAtEntryPointAttrName,
+ ArrayAttr::get(op->getContext(), entryPointNextAccess));
});
}
};
diff --git a/mlir/test/lib/Analysis/DataFlow/TestDenseDataFlowAnalysis.h b/mlir/test/lib/Analysis/DataFlow/TestDenseDataFlowAnalysis.h
index 6012c90f84539..9b0508660e9cd 100644
--- a/mlir/test/lib/Analysis/DataFlow/TestDenseDataFlowAnalysis.h
+++ b/mlir/test/lib/Analysis/DataFlow/TestDenseDataFlowAnalysis.h
@@ -196,7 +196,7 @@ class UnderlyingValueAnalysis
ArrayRef<const UnderlyingValueLattice *> operands,
ArrayRef<UnderlyingValueLattice *> results) override {
// Hook to test error propagation from visitOperation.
- if (op->hasAttr("always_fail"))
+ if (op->hasDiscardableAttr("always_fail"))
return op->emitError("this op is always fails");
setAllToEntryStates(results);
diff --git a/mlir/test/lib/Analysis/DataFlow/TestDenseForwardDataFlowAnalysis.cpp b/mlir/test/lib/Analysis/DataFlow/TestDenseForwardDataFlowAnalysis.cpp
index f2384f32948a2..c8b67b4ba61c0 100644
--- a/mlir/test/lib/Analysis/DataFlow/TestDenseForwardDataFlowAnalysis.cpp
+++ b/mlir/test/lib/Analysis/DataFlow/TestDenseForwardDataFlowAnalysis.cpp
@@ -252,7 +252,7 @@ struct TestLastModifiedPass
// Note that if the underlying value could not be computed or is unknown, we
// conservatively treat the result also unknown.
op->walk([&](Operation *op) {
- auto tag = op->getAttrOfType<StringAttr>("tag");
+ auto tag = op->getDiscardableAttrOfType<StringAttr>("tag");
if (!tag)
return;
os << "test_tag: " << tag.getValue() << ":\n";
@@ -285,7 +285,8 @@ struct TestLastModifiedPass
} else {
for (Operation *lastModifier : lastMod->get()) {
if (auto tagName =
- lastModifier->getAttrOfType<StringAttr>("tag_name")) {
+ lastModifier->getDiscardableAttrOfType<StringAttr>(
+ "tag_name")) {
os << " - " << tagName.getValue() << "\n";
} else {
os << " - " << lastModifier->getName() << "\n";
diff --git a/mlir/test/lib/Analysis/DataFlow/TestIntegerDivisibilityAnalysis.cpp b/mlir/test/lib/Analysis/DataFlow/TestIntegerDivisibilityAnalysis.cpp
index 626cbc0fac7aa..24d01c61e3783 100644
--- a/mlir/test/lib/Analysis/DataFlow/TestIntegerDivisibilityAnalysis.cpp
+++ b/mlir/test/lib/Analysis/DataFlow/TestIntegerDivisibilityAnalysis.cpp
@@ -71,7 +71,8 @@ struct TestIntegerDivisibilityAnalysisPass
const auto *lattice =
solver.lookupState<IntegerDivisibilityLattice>(value);
if (!lattice || lattice->getValue().isUninitialized()) {
- op->setAttr("divisibility", StringAttr::get(context, "uninitialized"));
+ op->setDiscardableAttr("divisibility",
+ StringAttr::get(context, "uninitialized"));
continue;
}
@@ -80,7 +81,7 @@ struct TestIntegerDivisibilityAnalysisPass
std::string result;
llvm::raw_string_ostream os(result);
os << "udiv = " << div.udiv() << ", sdiv = " << div.sdiv();
- op->setAttr("divisibility", StringAttr::get(context, result));
+ op->setDiscardableAttr("divisibility", StringAttr::get(context, result));
}
}
};
diff --git a/mlir/test/lib/Analysis/DataFlow/TestLivenessAnalysis.cpp b/mlir/test/lib/Analysis/DataFlow/TestLivenessAnalysis.cpp
index 2c9f46411f602..22c2a6bffd52a 100644
--- a/mlir/test/lib/Analysis/DataFlow/TestLivenessAnalysis.cpp
+++ b/mlir/test/lib/Analysis/DataFlow/TestLivenessAnalysis.cpp
@@ -38,7 +38,7 @@ struct TestLivenessAnalysisPass
raw_ostream &os = llvm::outs();
op->walk([&](Operation *op) {
- auto tag = op->getAttrOfType<StringAttr>("tag");
+ auto tag = op->getDiscardableAttrOfType<StringAttr>("tag");
if (!tag)
return;
os << "test_tag: " << tag.getValue() << ":\n";
diff --git a/mlir/test/lib/Analysis/DataFlow/TestSparseBackwardDataFlowAnalysis.cpp b/mlir/test/lib/Analysis/DataFlow/TestSparseBackwardDataFlowAnalysis.cpp
index b1978880e2bd6..18c74093e518f 100644
--- a/mlir/test/lib/Analysis/DataFlow/TestSparseBackwardDataFlowAnalysis.cpp
+++ b/mlir/test/lib/Analysis/DataFlow/TestSparseBackwardDataFlowAnalysis.cpp
@@ -104,7 +104,7 @@ WrittenToAnalysis::visitOperation(Operation *op, ArrayRef<WrittenTo *> operands,
ArrayRef<const WrittenTo *> results) {
if (auto store = dyn_cast<memref::StoreOp>(op)) {
SetVector<StringAttr> newWrites;
- newWrites.insert(op->getAttrOfType<StringAttr>("tag_name"));
+ newWrites.insert(op->getDiscardableAttrOfType<StringAttr>("tag_name"));
propagateIfChanged(operands[0],
operands[0]->getValue().addWrites(newWrites));
return success();
@@ -148,7 +148,7 @@ void WrittenToAnalysis::visitExternalCall(CallOpInterface call,
for (WrittenTo *lattice : operands) {
SetVector<StringAttr> newWrites;
- StringAttr name = call->getAttrOfType<StringAttr>("tag_name");
+ StringAttr name = call->getDiscardableAttrOfType<StringAttr>("tag_name");
if (!name) {
name = StringAttr::get(call->getContext(),
call.getOperation()->getName().getStringRef());
@@ -194,7 +194,7 @@ struct TestWrittenToPass
raw_ostream &os = llvm::outs();
op->walk([&](Operation *op) {
- auto tag = op->getAttrOfType<StringAttr>("tag");
+ auto tag = op->getDiscardableAttrOfType<StringAttr>("tag");
if (!tag)
return;
os << "test_tag: " << tag.getValue() << ":\n";
diff --git a/mlir/test/lib/Analysis/TestAliasAnalysis.cpp b/mlir/test/lib/Analysis/TestAliasAnalysis.cpp
index 0125e403272a8..f5eaed98f0268 100644
--- a/mlir/test/lib/Analysis/TestAliasAnalysis.cpp
+++ b/mlir/test/lib/Analysis/TestAliasAnalysis.cpp
@@ -21,14 +21,15 @@ using namespace mlir;
/// Print a value that is used as an operand of an alias query.
static void printAliasOperand(Operation *op) {
- llvm::errs() << op->getAttrOfType<StringAttr>("test.ptr").getValue();
+ llvm::errs()
+ << op->getDiscardableAttrOfType<StringAttr>("test.ptr").getValue();
}
static void printAliasOperand(Value value) {
if (BlockArgument arg = dyn_cast<BlockArgument>(value)) {
Region *region = arg.getParentRegion();
unsigned parentBlockNumber = arg.getOwner()->computeBlockNumber();
llvm::errs() << region->getParentOp()
- ->getAttrOfType<StringAttr>("test.ptr")
+ ->getDiscardableAttrOfType<StringAttr>("test.ptr")
.getValue()
<< ".region" << region->getRegionNumber();
if (parentBlockNumber != 0)
diff --git a/mlir/test/lib/Analysis/TestDataFlowFramework.cpp b/mlir/test/lib/Analysis/TestDataFlowFramework.cpp
index f29136853a9cd..98fbcd8c9b12c 100644
--- a/mlir/test/lib/Analysis/TestDataFlowFramework.cpp
+++ b/mlir/test/lib/Analysis/TestDataFlowFramework.cpp
@@ -238,7 +238,7 @@ void FooAnalysis::visitOperation(Operation *op) {
result |= state->set(*prevState);
// Modify the state with the attribute, if specified.
- if (auto attr = op->getAttrOfType<IntegerAttr>(kFooAttrName)) {
+ if (auto attr = op->getDiscardableAttrOfType<IntegerAttr>(kFooAttrName)) {
uint64_t value = attr.getType().isUnsignedInteger()
? attr.getUInt()
: static_cast<uint64_t>(attr.getInt());
@@ -301,7 +301,7 @@ void BarAnalysis::visitOperation(Operation *op) {
getOrCreateFor<BarState>(point, getProgramPointBefore(op));
result |= state->join(*prevState);
- if (op->hasAttr(kTagAttrName)) {
+ if (op->hasDiscardableAttr(kTagAttrName)) {
const FooState *fooState = getOrCreateFor<FooState>(point, point);
if (fooState->isUninitialized())
return;
@@ -321,7 +321,7 @@ void TestFooAnalysisPass::runOnOperation() {
os << "function: @" << func.getSymName() << "\n";
func.walk([&](Operation *op) {
- auto tag = op->getAttrOfType<StringAttr>(kTagAttrName);
+ auto tag = op->getDiscardableAttrOfType<StringAttr>(kTagAttrName);
if (!tag)
return;
const FooState *state =
@@ -344,7 +344,7 @@ void TestStagedAnalysesPass::runOnOperation() {
return signalPassFailure();
func.walk([&](Operation *op) {
- if (!op->hasAttr(kTagAttrName))
+ if (!op->hasDiscardableAttr(kTagAttrName))
return;
ProgramPoint *point = solver.getProgramPointAfter(op);
@@ -353,9 +353,10 @@ void TestStagedAnalysesPass::runOnOperation() {
assert(fooState && !fooState->isUninitialized());
assert(barState && !barState->isUninitialized());
- op->setAttr(kFooStateAttrName,
- builder.getI64IntegerAttr(fooState->getValue()));
- op->setAttr(kBarStateAttrName, builder.getBoolAttr(barState->getValue()));
+ op->setDiscardableAttr(kFooStateAttrName,
+ builder.getI64IntegerAttr(fooState->getValue()));
+ op->setDiscardableAttr(kBarStateAttrName,
+ builder.getBoolAttr(barState->getValue()));
});
}
diff --git a/mlir/test/lib/Analysis/TestSlice.cpp b/mlir/test/lib/Analysis/TestSlice.cpp
index 7e8320dbf3ec3..5055a7b36265c 100644
--- a/mlir/test/lib/Analysis/TestSlice.cpp
+++ b/mlir/test/lib/Analysis/TestSlice.cpp
@@ -31,14 +31,14 @@ struct TestTopologicalSortPass
void runOnOperation() override {
SetVector<Operation *> toSort;
getOperation().walk([&](Operation *op) {
- if (op->hasAttrOfType<UnitAttr>(kToSortMark))
+ if (op->hasDiscardableAttrOfType<UnitAttr>(kToSortMark))
toSort.insert(op);
});
auto i32Type = IntegerType::get(&getContext(), 32);
SetVector<Operation *> sortedOps = topologicalSort(toSort);
for (auto [index, op] : llvm::enumerate(sortedOps))
- op->setAttr(kOrderIndex, IntegerAttr::get(i32Type, index));
+ op->setDiscardableAttr(kOrderIndex, IntegerAttr::get(i32Type, index));
}
};
diff --git a/mlir/test/lib/Analysis/TestTopologicalSort.cpp b/mlir/test/lib/Analysis/TestTopologicalSort.cpp
index bd7e60f1ecc33..f219c8cf0a341 100644
--- a/mlir/test/lib/Analysis/TestTopologicalSort.cpp
+++ b/mlir/test/lib/Analysis/TestTopologicalSort.cpp
@@ -31,14 +31,14 @@ struct TestTopologicalSortAnalysisPass
OpBuilder builder(op->getContext());
WalkResult result = op->walk([&](Operation *root) {
- if (!root->hasAttr("root"))
+ if (!root->hasDiscardableAttr("root"))
return WalkResult::advance();
SmallVector<Operation *> selectedOps;
root->walk([&](Operation *selected) {
- if (!selected->hasAttr("selected"))
+ if (!selected->hasDiscardableAttr("selected"))
return WalkResult::advance();
- if (root->hasAttr("ordered")) {
+ if (root->hasDiscardableAttr("ordered")) {
// If the root has an "ordered" attribute, we fill the selectedOps
// vector in a certain order.
int64_t pos =
@@ -65,7 +65,7 @@ struct TestTopologicalSortAnalysisPass
}
for (const auto &it : llvm::enumerate(selectedOps))
- it.value()->setAttr("pos", builder.getIndexAttr(it.index()));
+ it.value()->setDiscardableAttr("pos", builder.getIndexAttr(it.index()));
return WalkResult::advance();
});
More information about the Mlir-commits
mailing list