[Mlir-commits] [mlir] [mlir][dataflow] Update dataflow tutorial doc and add dataflow example code (PR #149296)
Mehdi Amini
llvmlistbot at llvm.org
Fri Aug 8 08:04:00 PDT 2025
================
@@ -237,60 +228,91 @@ function for the operation, that is specific to our analysis. A simple
implementation for our example is shown below:
```c++
-class MetadataAnalysis : public ForwardDataFlowAnalysis<MetadataLatticeValue> {
+class MetadataAnalysis
+ : public SparseForwardDataFlowAnalysis<MetadataLatticeValueLattice> {
public:
- using ForwardDataFlowAnalysis<MetadataLatticeValue>::ForwardDataFlowAnalysis;
-
- ChangeResult visitOperation(
- Operation *op, ArrayRef<LatticeElement<ValueT> *> operands) override {
- DictionaryAttr metadata = op->getAttrOfType<DictionaryAttr>("metadata");
-
- // If we have no metadata for this operation, we will conservatively mark
- // all of the results as having reached a pessimistic fixpoint.
- if (!metadata)
- return markAllPessimisticFixPoint(op->getResults());
-
- // Otherwise, we will compute a lattice value for the metadata and join it
- // into the current lattice element for all of our results.
- MetadataLatticeValue latticeValue(metadata);
- ChangeResult result = ChangeResult::NoChange;
- for (Value value : op->getResults()) {
- // We grab the lattice element for `value` via `getLatticeElement` and
- // then join it with the lattice value for this operation's metadata. Note
- // that during the analysis phase, it is fine to freely create a new
- // lattice element for a value. This is why we don't use the
- // `lookupLatticeElement` method here.
- result |= getLatticeElement(value).join(latticeValue);
- }
- return result;
+ using SparseForwardDataFlowAnalysis::SparseForwardDataFlowAnalysis;
+ LogicalResult
+ visitOperation(Operation *op,
+ ArrayRef<const MetadataLatticeValueLattice *> operands,
+ ArrayRef<MetadataLatticeValueLattice *> results) override {
+ DictionaryAttr metadata = op->getAttrOfType<DictionaryAttr>("metadata");
+ // If we have no metadata for this operation and the operands is empty, we
+ // will conservatively mark all of the results as having reached a pessimistic
+ // fixpoint.
+ if (!metadata && operands.empty()) {
+ setAllToEntryStates(results);
+ return success();
+ }
+
+ MetadataLatticeValue latticeValue;
+ if (metadata)
+ latticeValue = MetadataLatticeValue(metadata);
+
+ // Otherwise, we will compute a lattice value for the metadata and join it
+ // into the current lattice element for all of our results.`results` stores
+ // the lattices corresponding to the results of op, We use a loop to traverse
+ // them.
+ for (auto result : results) {
+
+ // `isChanged` records whether the result has been changed.
+ ChangeResult isChanged = ChangeResult::NoChange;
+
+ // Op's metadata is joined result's lattice.
+ isChanged |= result->join(latticeValue);
+
+ // All lattice of operands of op are joined to the lattice of result.
+ for (auto operand : operands)
+ isChanged |= result->join(*operand);
+
+ propagateIfChanged(result, isChanged);
+ }
+ return success();
}
};
```
With that, we have all of the necessary components to compute our analysis.
-After the analysis has been computed, we can grab any computed information for
-values by using `lookupLatticeElement`. We use this function over
-`getLatticeElement` as the analysis is not guaranteed to visit all values, e.g.
-if the value is in a unreachable block, and we don't want to create a new
-uninitialized lattice element in this case. See below for a quick example:
+After the analysis has been computed, we need to run our analysis using
+`DataFlowSolver`, and we can grab any computed information for values by
+using `lookupState`. See below for a quick example, after the pass runs the
+analysis, we print the metadata of each op's results.
```c++
void MyPass::runOnOperation() {
- MetadataAnalysis analysis(&getContext());
- analysis.run(getOperation());
+ Operation *op = getOperation();
+ DataFlowSolver solver;
+ solver.load<DeadCodeAnalysis>();
+ solver.load<MetadataAnalysis>();
+ if (failed(solver.initializeAndRun(op)))
+ return signalPassFailure();
+
+ // If an op has more than one result, then the lattice is the same for each
+ // result, and we just print one of the results.
+ op->walk([&](Operation *op) {
+ if (op->getNumResults()) {
+ Value result = op->getResult(0);
+ auto lattice = solver.lookupState<MetadataLatticeValueLattice>(result);
+ lattice->print(llvm::outs());
----------------
joker-eph wrote:
```suggestion
llvm::outs() << OpWithFlags(op, OpPrintingFlags().skipRegions()) << " : ";
lattice->print(llvm::outs());
```
Seems like worth it to print the op to understand what the states correlates to.
https://github.com/llvm/llvm-project/pull/149296
More information about the Mlir-commits
mailing list