[Mlir-commits] [flang] [mlir] [mlir][Analysis] Add dependency declaration for dataflow analyses (PR #193112)

Ivan Butygin llvmlistbot at llvm.org
Wed Apr 22 04:04:39 PDT 2026


https://github.com/Hardcode84 updated https://github.com/llvm/llvm-project/pull/193112

>From cd036280f85695529cc0e52f5c5e0628ab32e188 Mon Sep 17 00:00:00 2001
From: Ivan Butygin <ivan.butygin at gmail.com>
Date: Tue, 21 Apr 2026 00:54:11 +0200
Subject: [PATCH 1/3] [mlir][Analysis] Add dependency declaration for dataflow
 analyses

DataFlowAnalysis subclasses can now declare required sibling analyses
via getDependentAnalyses(AnalysisDependencies &). The solver validates
them by TypeID at initializeAndRun and emits a consolidated diagnostic
listing every missing dep with its requester. Dependencies are not
auto-loaded because load<T> accepts arbitrary constructor arguments the
framework cannot synthesize; callers keep control of instantiation, the
solver just enforces the contract.

The four abstract driver bases (Sparse/Dense x Forward/Backward) declare
DeadCodeAnalysis as a hard dependency, and additionally assert it in
initialize() as a debug-only check against subclasses that override
getDependentAnalyses without chaining to the base.

Also:
- New DataFlowSolver::lookupAnalysis<T>() (exact-TypeID match).
- load<T>() asserts no duplicate load.
- Consolidate the existing debugName (gated on LLVM_ENABLE_ABI_BREAKING_CHECKS)
  with the new analysisID/analysisName into always-present members
  populated by load() after construction.
- Explicit TypeIDs (MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID) for
  analyses defined in anonymous namespaces.
- Document the soft DeadCodeAnalysis <-> SparseConstantPropagation
  circular co-dependency in DeadCodeAnalysis.h and Utils.h.
- Two lit tests covering single-requester and multi-requester
  missing-dep diagnostics.

Made-with: Cursor
---
 .../mlir/Analysis/DataFlow/DeadCodeAnalysis.h |   9 ++
 .../mlir/Analysis/DataFlow/DenseAnalysis.h    |   8 ++
 .../mlir/Analysis/DataFlow/SparseAnalysis.h   |   8 ++
 mlir/include/mlir/Analysis/DataFlow/Utils.h   |  11 +-
 .../include/mlir/Analysis/DataFlowFramework.h | 113 ++++++++++++++++--
 mlir/lib/Analysis/DataFlow/DenseAnalysis.cpp  |  14 +++
 mlir/lib/Analysis/DataFlow/SparseAnalysis.cpp |  21 ++++
 mlir/lib/Analysis/DataFlowFramework.cpp       |  47 +++++++-
 .../XeGPU/Transforms/XeGPUPropagateLayout.cpp |   2 +
 .../test-analysis-deps-multi-requester.mlir   |  11 ++
 .../Analysis/DataFlow/test-analysis-deps.mlir |  12 ++
 .../DataFlow/TestDeadCodeAnalysis.cpp         |   2 +
 .../TestDenseBackwardDataFlowAnalysis.cpp     |   2 +
 .../TestDenseForwardDataFlowAnalysis.cpp      |   2 +
 .../TestSparseBackwardDataFlowAnalysis.cpp    |   4 +-
 .../lib/Analysis/TestDataFlowFramework.cpp    |  77 ++++++++++++
 mlir/tools/mlir-opt/mlir-opt.cpp              |   6 +-
 17 files changed, 331 insertions(+), 18 deletions(-)
 create mode 100644 mlir/test/Analysis/DataFlow/test-analysis-deps-multi-requester.mlir
 create mode 100644 mlir/test/Analysis/DataFlow/test-analysis-deps.mlir

diff --git a/mlir/include/mlir/Analysis/DataFlow/DeadCodeAnalysis.h b/mlir/include/mlir/Analysis/DataFlow/DeadCodeAnalysis.h
index 3b2914cdd4c98..b05a323b2b3ec 100644
--- a/mlir/include/mlir/Analysis/DataFlow/DeadCodeAnalysis.h
+++ b/mlir/include/mlir/Analysis/DataFlow/DeadCodeAnalysis.h
@@ -173,6 +173,15 @@ class CFGEdge
 /// for region entry blocks and region control-flow operations. For the
 /// callgraph, this analysis determines the callsites and live returns of every
 /// function.
+///
+/// This analysis reads `Lattice<ConstantValue>` state to refine branches on
+/// constant conditions. The producer of that lattice is *not* declared as a
+/// hard dependency: if no producer is loaded, operand constants remain
+/// uninitialized and `DeadCodeAnalysis` conservatively marks all successors
+/// live (still correct, just less precise). Pair with
+/// `SparseConstantPropagation` (see `loadBaselineAnalyses` in
+/// `mlir/Analysis/DataFlow/Utils.h`) or a custom `Lattice<ConstantValue>`
+/// producer for best precision.
 class DeadCodeAnalysis : public DataFlowAnalysis {
 public:
   explicit DeadCodeAnalysis(DataFlowSolver &solver);
diff --git a/mlir/include/mlir/Analysis/DataFlow/DenseAnalysis.h b/mlir/include/mlir/Analysis/DataFlow/DenseAnalysis.h
index 82f86d06886b6..36a3b439dc2e1 100644
--- a/mlir/include/mlir/Analysis/DataFlow/DenseAnalysis.h
+++ b/mlir/include/mlir/Analysis/DataFlow/DenseAnalysis.h
@@ -73,6 +73,10 @@ class AbstractDenseForwardDataFlowAnalysis : public DataFlowAnalysis {
   /// may modify the program state; that is, every operation and block.
   LogicalResult initialize(Operation *top) override;
 
+  /// Dense forward analyses use `DeadCodeAnalysis` to skip dead blocks and
+  /// control-flow edges during propagation.
+  void getDependentAnalyses(AnalysisDependencies &deps) const override;
+
   /// Initialize lattice anchor equivalence class from the provided top-level
   /// operation.
   ///
@@ -367,6 +371,10 @@ class AbstractDenseBackwardDataFlowAnalysis : public DataFlowAnalysis {
   /// may modify the program state; that is, every operation and block.
   LogicalResult initialize(Operation *top) override;
 
+  /// Dense backward analyses use `DeadCodeAnalysis` to skip dead blocks and
+  /// control-flow edges during propagation.
+  void getDependentAnalyses(AnalysisDependencies &deps) const override;
+
   /// Initialize lattice anchor equivalence class from the provided top-level
   /// operation.
   ///
diff --git a/mlir/include/mlir/Analysis/DataFlow/SparseAnalysis.h b/mlir/include/mlir/Analysis/DataFlow/SparseAnalysis.h
index df50d8d193aeb..555efe8f802e9 100644
--- a/mlir/include/mlir/Analysis/DataFlow/SparseAnalysis.h
+++ b/mlir/include/mlir/Analysis/DataFlow/SparseAnalysis.h
@@ -193,6 +193,10 @@ class AbstractSparseForwardDataFlowAnalysis : public DataFlowAnalysis {
   /// accordingly.  Otherwise, the operation transfer function is invoked.
   LogicalResult visit(ProgramPoint *point) override;
 
+  /// Sparse forward analyses use `DeadCodeAnalysis` to skip dead blocks and
+  /// control-flow edges during propagation.
+  void getDependentAnalyses(AnalysisDependencies &deps) const override;
+
 protected:
   explicit AbstractSparseForwardDataFlowAnalysis(DataFlowSolver &solver);
 
@@ -413,6 +417,10 @@ class AbstractSparseBackwardDataFlowAnalysis : public DataFlowAnalysis {
   /// Otherwise, invokes the operation transfer function (`visitOperationImpl`).
   LogicalResult visit(ProgramPoint *point) override;
 
+  /// Sparse backward analyses use `DeadCodeAnalysis` to skip dead blocks and
+  /// control-flow edges during propagation.
+  void getDependentAnalyses(AnalysisDependencies &deps) const override;
+
 protected:
   explicit AbstractSparseBackwardDataFlowAnalysis(
       DataFlowSolver &solver, SymbolTableCollection &symbolTable);
diff --git a/mlir/include/mlir/Analysis/DataFlow/Utils.h b/mlir/include/mlir/Analysis/DataFlow/Utils.h
index e97f2f70f609c..43fd7810e2682 100644
--- a/mlir/include/mlir/Analysis/DataFlow/Utils.h
+++ b/mlir/include/mlir/Analysis/DataFlow/Utils.h
@@ -23,8 +23,15 @@ namespace dataflow {
 /// Populates a DataFlowSolver with analyses that are required to ensure
 /// user-defined analyses are run properly.
 ///
+/// `DeadCodeAnalysis` and `SparseConstantPropagation` have a circular
+/// co-dependency: SCP only propagates along live CFG edges (produced by DCA),
+/// and DCA refines branches using `Lattice<ConstantValue>` (produced by SCP).
+/// Only SCP's dep on DCA is declared (inherited from the sparse forward driver
+/// base); DCA works without SCP at reduced precision, so clients are free to
+/// substitute another `Lattice<ConstantValue>` producer.
+///
 /// This helper is intended to be an interim fix until a more robust solution
-/// can be implemented in the DataFlow framework directly. Cf.
+/// can be implemented in the DataFlow framework directly. See
 /// https://discourse.llvm.org/t/mlir-dead-code-analysis/67568
 inline void loadBaselineAnalyses(DataFlowSolver &solver) {
   solver.load<dataflow::DeadCodeAnalysis>();
@@ -34,4 +41,4 @@ inline void loadBaselineAnalyses(DataFlowSolver &solver) {
 } // end namespace dataflow
 } // end namespace mlir
 
-#endif // MLIR_ANALYSIS_DATAFLOW_INTEGERANGEANALYSIS_H
+#endif // MLIR_ANALYSIS_DATAFLOW_UTILS_H
diff --git a/mlir/include/mlir/Analysis/DataFlowFramework.h b/mlir/include/mlir/Analysis/DataFlowFramework.h
index 87ec01a918d90..0d766dffc77e9 100644
--- a/mlir/include/mlir/Analysis/DataFlowFramework.h
+++ b/mlir/include/mlir/Analysis/DataFlowFramework.h
@@ -28,6 +28,52 @@
 
 namespace mlir {
 
+class DataFlowAnalysis;
+
+//===----------------------------------------------------------------------===//
+// AnalysisDependencies
+//===----------------------------------------------------------------------===//
+
+/// Helper used by `DataFlowAnalysis::getDependentAnalyses` to declare the
+/// analyses that must be loaded into the solver for an analysis to run
+/// correctly. Declared analyses are not auto-loaded by the solver; callers
+/// are expected to load them explicitly with the appropriate constructor
+/// arguments. `DataFlowSolver::initializeAndRun` fails with a diagnostic if
+/// any declared dependency is missing.
+///
+/// Dependencies are matched by `TypeID`. Analyses defined inside an
+/// anonymous namespace must therefore provide an explicit TypeID via
+/// `MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID` (see
+/// `mlir/Support/TypeID.h`).
+class AnalysisDependencies {
+public:
+  /// A declared dependency. `typeID` is used for matching; `name` is
+  /// purely informational and is used in diagnostics.
+  struct Dependency {
+    TypeID typeID;
+    StringRef name;
+  };
+
+  /// Declare that the enclosing analysis depends on `AnalysisT`. Repeated
+  /// declarations of the same dependency are deduplicated so validation
+  /// diagnostics do not carry redundant notes.
+  template <typename AnalysisT>
+  void insert() {
+    static_assert(std::is_base_of_v<DataFlowAnalysis, AnalysisT>,
+                  "dependency must derive from DataFlowAnalysis");
+    TypeID id = TypeID::get<AnalysisT>();
+    for (const Dependency &dep : deps)
+      if (dep.typeID == id)
+        return;
+    deps.push_back({id, llvm::getTypeName<AnalysisT>()});
+  }
+
+  ArrayRef<Dependency> getDependencies() const { return deps; }
+
+private:
+  SmallVector<Dependency> deps;
+};
+
 //===----------------------------------------------------------------------===//
 // ChangeResult
 //===----------------------------------------------------------------------===//
@@ -261,9 +307,6 @@ struct LatticeAnchor
   Location getLoc() const;
 };
 
-/// Forward declaration of the data-flow analysis class.
-class DataFlowAnalysis;
-
 } // namespace mlir
 
 template <>
@@ -331,8 +374,17 @@ class DataFlowSolver {
   template <typename AnalysisT, typename... Args>
   AnalysisT *load(Args &&...args);
 
+  /// Return the loaded analysis of type `AnalysisT`, or nullptr if no such
+  /// analysis is loaded. Matches are by exact TypeID: subclasses of
+  /// `AnalysisT` will not be returned when querying for `AnalysisT`.
+  template <typename AnalysisT>
+  AnalysisT *lookupAnalysis() const;
+
   /// Initialize the children analyses starting from the provided top-level
   /// operation and run the analysis until fixpoint.
+  ///
+  /// Fails with a diagnostic if any child analysis declares a dependency via
+  /// `DataFlowAnalysis::getDependentAnalyses` that has not been loaded.
   LogicalResult initializeAndRun(Operation *top);
 
   /// Lookup an analysis state for the given lattice anchor. Returns null if one
@@ -627,9 +679,29 @@ class DataFlowAnalysis {
   ///
   /// This function will union lattice anchor to same equivalent class if the
   /// analysis can determine the lattice content of lattice anchor is
-  /// necessarily identical under the corrensponding lattice type.
+  /// necessarily identical under the corresponding lattice type.
   virtual void initializeEquivalentLatticeAnchor(Operation *top) {}
 
+  /// Register the analyses that this analysis depends on. Each dependency
+  /// must be loaded into the solver before `initializeAndRun` is called.
+  ///
+  /// Dependencies are not auto-loaded, because `DataFlowSolver::load` accepts
+  /// arbitrary constructor arguments that the framework cannot synthesize.
+  /// Subclasses that override this method should call the parent's
+  /// `getDependentAnalyses` first to preserve inherited dependencies.
+  virtual void getDependentAnalyses(AnalysisDependencies &deps) const {}
+
+  /// Return the TypeID of this analysis. Valid only after
+  /// `DataFlowSolver::load<AnalysisT>` has returned; must not be read from
+  /// the analysis constructor body. Used by the solver to match declared
+  /// dependencies.
+  TypeID getTypeID() const { return analysisID; }
+
+  /// Return a printable name for the analysis. Valid only after
+  /// `DataFlowSolver::load<AnalysisT>` has returned; must not be read from
+  /// the analysis constructor body. Used for diagnostics and debug logging.
+  StringRef getName() const { return analysisName; }
+
 protected:
   /// Create a dependency between the given analysis state and lattice anchor
   /// on this analysis.
@@ -696,28 +768,47 @@ class DataFlowAnalysis {
   /// Return the configuration of the solver used for this analysis.
   const DataFlowConfig &getSolverConfig() const { return solver.getConfig(); }
 
-#if LLVM_ENABLE_ABI_BREAKING_CHECKS
-  /// When compiling with debugging, keep a name for the analyis.
-  StringRef debugName;
-#endif // LLVM_ENABLE_ABI_BREAKING_CHECKS
+  /// Return the parent solver.
+  const DataFlowSolver &getSolver() const { return solver; }
 
 private:
   /// The parent data-flow solver.
   DataFlowSolver &solver;
 
+  /// The TypeID of the concrete analysis type. Set by `DataFlowSolver::load`,
+  /// used to match declared dependencies.
+  TypeID analysisID;
+
+  /// Printable name of the analysis. Set by `DataFlowSolver::load`. Used for
+  /// diagnostics when reporting missing dependencies and for debug logging.
+  StringRef analysisName;
+
   /// Allow the data-flow solver to access the internals of this class.
   friend class DataFlowSolver;
 };
 
 template <typename AnalysisT, typename... Args>
 AnalysisT *DataFlowSolver::load(Args &&...args) {
+  assert(lookupAnalysis<AnalysisT>() == nullptr &&
+         "analysis of this type already loaded into the solver");
   childAnalyses.emplace_back(new AnalysisT(*this, std::forward<Args>(args)...));
-#if LLVM_ENABLE_ABI_BREAKING_CHECKS
-  childAnalyses.back()->debugName = llvm::getTypeName<AnalysisT>();
-#endif // LLVM_ENABLE_ABI_BREAKING_CHECKS
+  DataFlowAnalysis &analysis = *childAnalyses.back();
+  analysis.analysisID = TypeID::get<AnalysisT>();
+  analysis.analysisName = llvm::getTypeName<AnalysisT>();
   return static_cast<AnalysisT *>(childAnalyses.back().get());
 }
 
+template <typename AnalysisT>
+AnalysisT *DataFlowSolver::lookupAnalysis() const {
+  // Linear search over `childAnalyses`. Solvers typically hold a handful of
+  // analyses, so a hash map would cost more than it saves.
+  TypeID id = TypeID::get<AnalysisT>();
+  for (const std::unique_ptr<DataFlowAnalysis> &analysis : childAnalyses)
+    if (analysis->getTypeID() == id)
+      return static_cast<AnalysisT *>(analysis.get());
+  return nullptr;
+}
+
 template <typename StateT>
 LatticeAnchor
 DataFlowSolver::getLeaderAnchorOrSelf(LatticeAnchor latticeAnchor) const {
diff --git a/mlir/lib/Analysis/DataFlow/DenseAnalysis.cpp b/mlir/lib/Analysis/DataFlow/DenseAnalysis.cpp
index 22bc0b32a9bd1..37d7ce76e47ce 100644
--- a/mlir/lib/Analysis/DataFlow/DenseAnalysis.cpp
+++ b/mlir/lib/Analysis/DataFlow/DenseAnalysis.cpp
@@ -30,6 +30,11 @@ using namespace mlir::dataflow;
 // AbstractDenseForwardDataFlowAnalysis
 //===----------------------------------------------------------------------===//
 
+void AbstractDenseForwardDataFlowAnalysis::getDependentAnalyses(
+    AnalysisDependencies &deps) const {
+  deps.insert<DeadCodeAnalysis>();
+}
+
 void AbstractDenseForwardDataFlowAnalysis::initializeEquivalentLatticeAnchor(
     Operation *top) {
   LDBG() << "initializeEquivalentLatticeAnchor: "
@@ -48,6 +53,8 @@ void AbstractDenseForwardDataFlowAnalysis::initializeEquivalentLatticeAnchor(
 }
 
 LogicalResult AbstractDenseForwardDataFlowAnalysis::initialize(Operation *top) {
+  assert(getSolver().lookupAnalysis<DeadCodeAnalysis>() &&
+         "DeadCodeAnalysis must be loaded alongside a dense forward analysis");
   LDBG() << "initialize (forward): "
          << OpWithFlags(top, OpPrintingFlags().skipRegions());
   // Visit every operation and block.
@@ -356,6 +363,11 @@ void AbstractDenseForwardDataFlowAnalysis::visitRegionBranchOperation(
 // AbstractDenseBackwardDataFlowAnalysis
 //===----------------------------------------------------------------------===//
 
+void AbstractDenseBackwardDataFlowAnalysis::getDependentAnalyses(
+    AnalysisDependencies &deps) const {
+  deps.insert<DeadCodeAnalysis>();
+}
+
 void AbstractDenseBackwardDataFlowAnalysis::initializeEquivalentLatticeAnchor(
     Operation *top) {
   LDBG() << "initializeEquivalentLatticeAnchor (backward): "
@@ -375,6 +387,8 @@ void AbstractDenseBackwardDataFlowAnalysis::initializeEquivalentLatticeAnchor(
 
 LogicalResult
 AbstractDenseBackwardDataFlowAnalysis::initialize(Operation *top) {
+  assert(getSolver().lookupAnalysis<DeadCodeAnalysis>() &&
+         "DeadCodeAnalysis must be loaded alongside a dense backward analysis");
   LDBG() << "initialize (backward): "
          << OpWithFlags(top, OpPrintingFlags().skipRegions());
   // Visit every operation and block.
diff --git a/mlir/lib/Analysis/DataFlow/SparseAnalysis.cpp b/mlir/lib/Analysis/DataFlow/SparseAnalysis.cpp
index 90f2a588d1ca4..30f0a9c739533 100644
--- a/mlir/lib/Analysis/DataFlow/SparseAnalysis.cpp
+++ b/mlir/lib/Analysis/DataFlow/SparseAnalysis.cpp
@@ -51,8 +51,21 @@ AbstractSparseForwardDataFlowAnalysis::AbstractSparseForwardDataFlowAnalysis(
   registerAnchorKind<CFGEdge>();
 }
 
+void AbstractSparseForwardDataFlowAnalysis::getDependentAnalyses(
+    AnalysisDependencies &deps) const {
+  deps.insert<DeadCodeAnalysis>();
+}
+
 LogicalResult
 AbstractSparseForwardDataFlowAnalysis::initialize(Operation *top) {
+  // Sparse forward analyses require `DeadCodeAnalysis` to be loaded. This is
+  // normally enforced by the solver's dependency validator, but a concrete
+  // subclass can silently drop the base's declared dependency by overriding
+  // `getDependentAnalyses` without calling the parent. Assert here as a
+  // second line of defense.
+  assert(getSolver().lookupAnalysis<DeadCodeAnalysis>() &&
+         "DeadCodeAnalysis must be loaded alongside a sparse forward analysis");
+
   // Mark the entry block arguments as having reached their pessimistic
   // fixpoints.
   for (Region &region : top->getRegions()) {
@@ -371,8 +384,16 @@ AbstractSparseBackwardDataFlowAnalysis::AbstractSparseBackwardDataFlowAnalysis(
   registerAnchorKind<CFGEdge>();
 }
 
+void AbstractSparseBackwardDataFlowAnalysis::getDependentAnalyses(
+    AnalysisDependencies &deps) const {
+  deps.insert<DeadCodeAnalysis>();
+}
+
 LogicalResult
 AbstractSparseBackwardDataFlowAnalysis::initialize(Operation *top) {
+  assert(getSolver().lookupAnalysis<DeadCodeAnalysis>() &&
+         "DeadCodeAnalysis must be loaded alongside a sparse backward "
+         "analysis");
   return initializeRecursively(top);
 }
 
diff --git a/mlir/lib/Analysis/DataFlowFramework.cpp b/mlir/lib/Analysis/DataFlowFramework.cpp
index 258bcf312afc5..a1a97097c36d9 100644
--- a/mlir/lib/Analysis/DataFlowFramework.cpp
+++ b/mlir/lib/Analysis/DataFlowFramework.cpp
@@ -7,10 +7,12 @@
 //===----------------------------------------------------------------------===//
 
 #include "mlir/Analysis/DataFlowFramework.h"
+#include "mlir/IR/Diagnostics.h"
 #include "mlir/IR/Location.h"
 #include "mlir/IR/Operation.h"
 #include "mlir/IR/SymbolTable.h"
 #include "mlir/IR/Value.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/iterator.h"
 #include "llvm/Config/abi-breaking.h"
@@ -109,7 +111,48 @@ Location LatticeAnchor::getLoc() const {
 // DataFlowSolver
 //===----------------------------------------------------------------------===//
 
+/// Emit a diagnostic listing all analyses whose declared dependencies are not
+/// loaded in the solver. Returns failure if any dependency is missing.
+static LogicalResult
+validateDependencies(Operation *top,
+                     ArrayRef<std::unique_ptr<DataFlowAnalysis>> analyses) {
+  llvm::SmallDenseSet<TypeID, 8> loaded;
+  for (const std::unique_ptr<DataFlowAnalysis> &analysis : analyses)
+    loaded.insert(analysis->getTypeID());
+
+  struct Missing {
+    StringRef requester;
+    AnalysisDependencies::Dependency dep;
+  };
+  SmallVector<Missing> missing;
+
+  for (const std::unique_ptr<DataFlowAnalysis> &analysis : analyses) {
+    AnalysisDependencies deps;
+    analysis->getDependentAnalyses(deps);
+    for (const AnalysisDependencies::Dependency &dep : deps.getDependencies()) {
+      if (!loaded.contains(dep.typeID))
+        missing.push_back({analysis->getName(), dep});
+    }
+  }
+
+  if (missing.empty())
+    return success();
+
+  InFlightDiagnostic err =
+      emitError(top->getLoc(),
+                "DataFlowSolver: missing required analyses; load each missing "
+                "analysis via `solver.load<T>()` before `initializeAndRun`");
+  for (const Missing &m : missing) {
+    err.attachNote() << "analysis '" << m.requester << "' requires '"
+                     << m.dep.name << "' (not loaded)";
+  }
+  return err;
+}
+
 LogicalResult DataFlowSolver::initializeAndRun(Operation *top) {
+  if (failed(validateDependencies(top, childAnalyses)))
+    return failure();
+
   // Enable enqueue to the worklist.
   isRunning = true;
   llvm::scope_exit guard([&]() { isRunning = false; });
@@ -127,7 +170,7 @@ LogicalResult DataFlowSolver::initializeAndRun(Operation *top) {
 
   // Initialize the analyses.
   for (DataFlowAnalysis &analysis : llvm::make_pointee_range(childAnalyses)) {
-    DATAFLOW_DEBUG(LDBG() << "Priming analysis: " << analysis.debugName);
+    DATAFLOW_DEBUG(LDBG() << "Priming analysis: " << analysis.getName());
     if (failed(analysis.initialize(top)))
       return failure();
   }
@@ -139,7 +182,7 @@ LogicalResult DataFlowSolver::initializeAndRun(Operation *top) {
     auto [point, analysis] = worklist.front();
     worklist.pop();
 
-    DATAFLOW_DEBUG(LDBG() << "Invoking '" << analysis->debugName
+    DATAFLOW_DEBUG(LDBG() << "Invoking '" << analysis->getName()
                           << "' on: " << *point);
     if (failed(analysis->visit(point)))
       return failure();
diff --git a/mlir/lib/Dialect/XeGPU/Transforms/XeGPUPropagateLayout.cpp b/mlir/lib/Dialect/XeGPU/Transforms/XeGPUPropagateLayout.cpp
index 686cb20e1976e..776b31efc167c 100644
--- a/mlir/lib/Dialect/XeGPU/Transforms/XeGPUPropagateLayout.cpp
+++ b/mlir/lib/Dialect/XeGPU/Transforms/XeGPUPropagateLayout.cpp
@@ -390,6 +390,8 @@ class LayoutInfoPropagation
   bool hasParamsOfLayoutKind(xegpu::DistributeLayoutAttr anchorLayout);
 
 public:
+  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(LayoutInfoPropagation)
+
   LayoutInfoPropagation(DataFlowSolver &solver,
                         SymbolTableCollection &symbolTable,
                         xegpu::LayoutKind layoutKind, unsigned indexBitWidth)
diff --git a/mlir/test/Analysis/DataFlow/test-analysis-deps-multi-requester.mlir b/mlir/test/Analysis/DataFlow/test-analysis-deps-multi-requester.mlir
new file mode 100644
index 0000000000000..cf7366e23d753
--- /dev/null
+++ b/mlir/test/Analysis/DataFlow/test-analysis-deps-multi-requester.mlir
@@ -0,0 +1,11 @@
+// RUN: mlir-opt %s -test-analysis-deps-multi-requester -verify-diagnostics
+
+// When multiple loaded analyses all depend on the same missing analysis, the
+// solver should emit one error with one note per requester.
+
+// expected-error @below {{DataFlowSolver: missing required analyses}}
+// expected-note-re @below {{FooDependentAnalysis' requires '{{.*}}FooAnalysis' (not loaded)}}
+// expected-note-re @below {{BazDependentAnalysis' requires '{{.*}}FooAnalysis' (not loaded)}}
+func.func @missing_dep_multi_requester() {
+  return
+}
diff --git a/mlir/test/Analysis/DataFlow/test-analysis-deps.mlir b/mlir/test/Analysis/DataFlow/test-analysis-deps.mlir
new file mode 100644
index 0000000000000..dae8cf522a0dc
--- /dev/null
+++ b/mlir/test/Analysis/DataFlow/test-analysis-deps.mlir
@@ -0,0 +1,12 @@
+// RUN: mlir-opt %s -test-analysis-deps -verify-diagnostics
+
+// The `FooDependentAnalysis` test analysis declares a dependency on
+// `FooAnalysis` but the test pass only loads `FooDependentAnalysis`, so
+// `initializeAndRun` must fail with a diagnostic naming both the requester and
+// the missing dep.
+
+// expected-error @below {{DataFlowSolver: missing required analyses}}
+// expected-note-re @below {{FooDependentAnalysis' requires '{{.*}}FooAnalysis' (not loaded)}}
+func.func @missing_dep() {
+  return
+}
diff --git a/mlir/test/lib/Analysis/DataFlow/TestDeadCodeAnalysis.cpp b/mlir/test/lib/Analysis/DataFlow/TestDeadCodeAnalysis.cpp
index 2dc77c9705d35..327e807873714 100644
--- a/mlir/test/lib/Analysis/DataFlow/TestDeadCodeAnalysis.cpp
+++ b/mlir/test/lib/Analysis/DataFlow/TestDeadCodeAnalysis.cpp
@@ -67,6 +67,8 @@ namespace {
 /// This is a simple analysis that implements a transfer function for constant
 /// operations.
 struct ConstantAnalysis : public DataFlowAnalysis {
+  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(ConstantAnalysis)
+
   using DataFlowAnalysis::DataFlowAnalysis;
 
   LogicalResult initialize(Operation *top) override {
diff --git a/mlir/test/lib/Analysis/DataFlow/TestDenseBackwardDataFlowAnalysis.cpp b/mlir/test/lib/Analysis/DataFlow/TestDenseBackwardDataFlowAnalysis.cpp
index 232bf14827556..f09df47e5f65e 100644
--- a/mlir/test/lib/Analysis/DataFlow/TestDenseBackwardDataFlowAnalysis.cpp
+++ b/mlir/test/lib/Analysis/DataFlow/TestDenseBackwardDataFlowAnalysis.cpp
@@ -51,6 +51,8 @@ class NextAccess : public AbstractDenseLattice, public AccessLatticeBase {
 
 class NextAccessAnalysis : public DenseBackwardDataFlowAnalysis<NextAccess> {
 public:
+  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(NextAccessAnalysis)
+
   NextAccessAnalysis(DataFlowSolver &solver, SymbolTableCollection &symbolTable,
                      bool assumeFuncReads = false)
       : DenseBackwardDataFlowAnalysis(solver, symbolTable),
diff --git a/mlir/test/lib/Analysis/DataFlow/TestDenseForwardDataFlowAnalysis.cpp b/mlir/test/lib/Analysis/DataFlow/TestDenseForwardDataFlowAnalysis.cpp
index 9236e98168883..f2384f32948a2 100644
--- a/mlir/test/lib/Analysis/DataFlow/TestDenseForwardDataFlowAnalysis.cpp
+++ b/mlir/test/lib/Analysis/DataFlow/TestDenseForwardDataFlowAnalysis.cpp
@@ -49,6 +49,8 @@ class LastModification : public AbstractDenseLattice, public AccessLatticeBase {
 class LastModifiedAnalysis
     : public DenseForwardDataFlowAnalysis<LastModification> {
 public:
+  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(LastModifiedAnalysis)
+
   explicit LastModifiedAnalysis(DataFlowSolver &solver, bool assumeFuncWrites)
       : DenseForwardDataFlowAnalysis(solver),
         assumeFuncWrites(assumeFuncWrites) {}
diff --git a/mlir/test/lib/Analysis/DataFlow/TestSparseBackwardDataFlowAnalysis.cpp b/mlir/test/lib/Analysis/DataFlow/TestSparseBackwardDataFlowAnalysis.cpp
index 4f19cc7144afc..8b26816745a64 100644
--- a/mlir/test/lib/Analysis/DataFlow/TestSparseBackwardDataFlowAnalysis.cpp
+++ b/mlir/test/lib/Analysis/DataFlow/TestSparseBackwardDataFlowAnalysis.cpp
@@ -1,4 +1,4 @@
-//===- TestBackwardDataFlowAnalysis.cpp - Test dead code analysis ---------===//
+//===- TestSparseBackwardDataFlowAnalysis.cpp - Test backward sparse ------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -70,6 +70,8 @@ struct WrittenTo : public Lattice<WrittenToLatticeValue> {
 /// is eventually written to.
 class WrittenToAnalysis : public SparseBackwardDataFlowAnalysis<WrittenTo> {
 public:
+  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(WrittenToAnalysis)
+
   WrittenToAnalysis(DataFlowSolver &solver, SymbolTableCollection &symbolTable,
                     bool assumeFuncWrites)
       : SparseBackwardDataFlowAnalysis(solver, symbolTable),
diff --git a/mlir/test/lib/Analysis/TestDataFlowFramework.cpp b/mlir/test/lib/Analysis/TestDataFlowFramework.cpp
index 4267fb42266ce..add1c8696b5a6 100644
--- a/mlir/test/lib/Analysis/TestDataFlowFramework.cpp
+++ b/mlir/test/lib/Analysis/TestDataFlowFramework.cpp
@@ -90,6 +90,77 @@ struct TestFooAnalysisPass
 
   void runOnOperation() override;
 };
+
+/// An analysis that declares a dependency on `FooAnalysis` but does nothing
+/// else. Used to test that `DataFlowSolver::initializeAndRun` reports missing
+/// dependencies via diagnostic.
+class FooDependentAnalysis : public DataFlowAnalysis {
+public:
+  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(FooDependentAnalysis)
+
+  using DataFlowAnalysis::DataFlowAnalysis;
+
+  LogicalResult initialize(Operation *) override { return success(); }
+  LogicalResult visit(ProgramPoint *) override { return success(); }
+
+  void getDependentAnalyses(AnalysisDependencies &deps) const override {
+    deps.insert<FooAnalysis>();
+  }
+};
+
+/// A second analysis that also declares a dependency on `FooAnalysis`. Paired
+/// with `FooDependentAnalysis` to test that the solver emits a separate
+/// diagnostic note per requester when multiple analyses share an unsatisfied
+/// dependency. The name is intentionally *not* a prefix/suffix of
+/// `FooDependentAnalysis` so lit-test regex matches stay disjoint.
+class BazDependentAnalysis : public DataFlowAnalysis {
+public:
+  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(BazDependentAnalysis)
+
+  using DataFlowAnalysis::DataFlowAnalysis;
+
+  LogicalResult initialize(Operation *) override { return success(); }
+  LogicalResult visit(ProgramPoint *) override { return success(); }
+
+  void getDependentAnalyses(AnalysisDependencies &deps) const override {
+    deps.insert<FooAnalysis>();
+  }
+};
+
+struct TestAnalysisDepsPass
+    : public PassWrapper<TestAnalysisDepsPass, OperationPass<func::FuncOp>> {
+  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestAnalysisDepsPass)
+
+  StringRef getArgument() const override { return "test-analysis-deps"; }
+
+  void runOnOperation() override {
+    DataFlowSolver solver;
+    solver.load<FooDependentAnalysis>();
+    if (failed(solver.initializeAndRun(getOperation())))
+      return signalPassFailure();
+  }
+};
+
+/// Loads two analyses that both depend on `FooAnalysis` (which is not loaded).
+/// The solver should emit one error with two notes, one per requester.
+struct TestAnalysisDepsMultiRequesterPass
+    : public PassWrapper<TestAnalysisDepsMultiRequesterPass,
+                         OperationPass<func::FuncOp>> {
+  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(
+      TestAnalysisDepsMultiRequesterPass)
+
+  StringRef getArgument() const override {
+    return "test-analysis-deps-multi-requester";
+  }
+
+  void runOnOperation() override {
+    DataFlowSolver solver;
+    solver.load<FooDependentAnalysis>();
+    solver.load<BazDependentAnalysis>();
+    if (failed(solver.initializeAndRun(getOperation())))
+      return signalPassFailure();
+  }
+};
 } // namespace
 
 LogicalResult FooAnalysis::initialize(Operation *top) {
@@ -182,5 +253,11 @@ void TestFooAnalysisPass::runOnOperation() {
 namespace mlir {
 namespace test {
 void registerTestFooAnalysisPass() { PassRegistration<TestFooAnalysisPass>(); }
+void registerTestAnalysisDepsPass() {
+  PassRegistration<TestAnalysisDepsPass>();
+}
+void registerTestAnalysisDepsMultiRequesterPass() {
+  PassRegistration<TestAnalysisDepsMultiRequesterPass>();
+}
 } // namespace test
 } // namespace mlir
diff --git a/mlir/tools/mlir-opt/mlir-opt.cpp b/mlir/tools/mlir-opt/mlir-opt.cpp
index 48b8c179bd1b0..b4c3939399782 100644
--- a/mlir/tools/mlir-opt/mlir-opt.cpp
+++ b/mlir/tools/mlir-opt/mlir-opt.cpp
@@ -98,8 +98,9 @@ void registerTestDominancePass();
 void registerTestDynamicPipelinePass();
 void registerTestRemarkPass();
 void registerTestEmulateNarrowTypePass();
+void registerTestAnalysisDepsMultiRequesterPass();
+void registerTestAnalysisDepsPass();
 void registerTestFooAnalysisPass();
-void registerTestComposeSubView();
 void registerTestMultiBuffering();
 void registerTestIRVisitorsPass();
 void registerTestGenericIRVisitorsPass();
@@ -246,8 +247,9 @@ static void registerTestPasses() {
   mlir::test::registerTestDynamicPipelinePass();
   mlir::test::registerTestRemarkPass();
   mlir::test::registerTestEmulateNarrowTypePass();
+  mlir::test::registerTestAnalysisDepsMultiRequesterPass();
+  mlir::test::registerTestAnalysisDepsPass();
   mlir::test::registerTestFooAnalysisPass();
-  mlir::test::registerTestComposeSubView();
   mlir::test::registerTestMultiBuffering();
   mlir::test::registerTestIRVisitorsPass();
   mlir::test::registerTestGenericIRVisitorsPass();

>From 69f2695f09f6333e5cf0d26ebd388f2ae62e9698 Mon Sep 17 00:00:00 2001
From: Ivan Butygin <ivan.butygin at gmail.com>
Date: Tue, 21 Apr 2026 01:17:24 +0200
Subject: [PATCH 2/3] fix flang

---
 flang/lib/Optimizer/Transforms/StackArrays.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/flang/lib/Optimizer/Transforms/StackArrays.cpp b/flang/lib/Optimizer/Transforms/StackArrays.cpp
index 3f49f60089dbd..70fdc2dca50ce 100644
--- a/flang/lib/Optimizer/Transforms/StackArrays.cpp
+++ b/flang/lib/Optimizer/Transforms/StackArrays.cpp
@@ -156,6 +156,7 @@ class LatticePoint : public mlir::dataflow::AbstractDenseLattice {
 class AllocationAnalysis
     : public mlir::dataflow::DenseForwardDataFlowAnalysis<LatticePoint> {
 public:
+  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(AllocationAnalysis)
   using DenseForwardDataFlowAnalysis::DenseForwardDataFlowAnalysis;
 
   mlir::LogicalResult visitOperation(mlir::Operation *op,

>From e606f4b888bc73087e996eadcd38e1e312bb76d6 Mon Sep 17 00:00:00 2001
From: Ivan Butygin <ivan.butygin at gmail.com>
Date: Wed, 22 Apr 2026 12:50:31 +0200
Subject: [PATCH 3/3] address review doc feedback on dataflow analysis
 dependencies

- Reframe AnalysisDependencies as the collection consulted at
  initializeAndRun, warn against overusing hard deps for precision.
- Broaden initializeAndRun failure-mode description (init, visit,
  and dependency validation).
- DataFlowAnalysis::getDependentAnalyses: say "chain to the parent's"
  and note declarations are deduplicated.
- Rewrite the four driver-base getDependentAnalyses override comments
  to describe the subclass contract (chain to preserve DeadCodeAnalysis,
  add extra deps) rather than restating what the base does.
- validateDependencies docstring: "Emit" -> "Emits".

Made-with: Cursor
---
 .../mlir/Analysis/DataFlow/DenseAnalysis.h    | 10 +++--
 .../mlir/Analysis/DataFlow/SparseAnalysis.h   | 10 +++--
 .../include/mlir/Analysis/DataFlowFramework.h | 38 ++++++++++++-------
 mlir/lib/Analysis/DataFlowFramework.cpp       |  4 +-
 4 files changed, 38 insertions(+), 24 deletions(-)

diff --git a/mlir/include/mlir/Analysis/DataFlow/DenseAnalysis.h b/mlir/include/mlir/Analysis/DataFlow/DenseAnalysis.h
index 36a3b439dc2e1..4583ca8051095 100644
--- a/mlir/include/mlir/Analysis/DataFlow/DenseAnalysis.h
+++ b/mlir/include/mlir/Analysis/DataFlow/DenseAnalysis.h
@@ -73,8 +73,9 @@ class AbstractDenseForwardDataFlowAnalysis : public DataFlowAnalysis {
   /// may modify the program state; that is, every operation and block.
   LogicalResult initialize(Operation *top) override;
 
-  /// Dense forward analyses use `DeadCodeAnalysis` to skip dead blocks and
-  /// control-flow edges during propagation.
+  /// Chain to this implementation from subclass overrides (so the
+  /// `DeadCodeAnalysis` dependency is preserved) and add any additional
+  /// dependencies of the concrete analysis.
   void getDependentAnalyses(AnalysisDependencies &deps) const override;
 
   /// Initialize lattice anchor equivalence class from the provided top-level
@@ -371,8 +372,9 @@ class AbstractDenseBackwardDataFlowAnalysis : public DataFlowAnalysis {
   /// may modify the program state; that is, every operation and block.
   LogicalResult initialize(Operation *top) override;
 
-  /// Dense backward analyses use `DeadCodeAnalysis` to skip dead blocks and
-  /// control-flow edges during propagation.
+  /// Chain to this implementation from subclass overrides (so the
+  /// `DeadCodeAnalysis` dependency is preserved) and add any additional
+  /// dependencies of the concrete analysis.
   void getDependentAnalyses(AnalysisDependencies &deps) const override;
 
   /// Initialize lattice anchor equivalence class from the provided top-level
diff --git a/mlir/include/mlir/Analysis/DataFlow/SparseAnalysis.h b/mlir/include/mlir/Analysis/DataFlow/SparseAnalysis.h
index 555efe8f802e9..ef0b2becd1d02 100644
--- a/mlir/include/mlir/Analysis/DataFlow/SparseAnalysis.h
+++ b/mlir/include/mlir/Analysis/DataFlow/SparseAnalysis.h
@@ -193,8 +193,9 @@ class AbstractSparseForwardDataFlowAnalysis : public DataFlowAnalysis {
   /// accordingly.  Otherwise, the operation transfer function is invoked.
   LogicalResult visit(ProgramPoint *point) override;
 
-  /// Sparse forward analyses use `DeadCodeAnalysis` to skip dead blocks and
-  /// control-flow edges during propagation.
+  /// Chain to this implementation from subclass overrides (so the
+  /// `DeadCodeAnalysis` dependency is preserved) and add any additional
+  /// dependencies of the concrete analysis.
   void getDependentAnalyses(AnalysisDependencies &deps) const override;
 
 protected:
@@ -417,8 +418,9 @@ class AbstractSparseBackwardDataFlowAnalysis : public DataFlowAnalysis {
   /// Otherwise, invokes the operation transfer function (`visitOperationImpl`).
   LogicalResult visit(ProgramPoint *point) override;
 
-  /// Sparse backward analyses use `DeadCodeAnalysis` to skip dead blocks and
-  /// control-flow edges during propagation.
+  /// Chain to this implementation from subclass overrides (so the
+  /// `DeadCodeAnalysis` dependency is preserved) and add any additional
+  /// dependencies of the concrete analysis.
   void getDependentAnalyses(AnalysisDependencies &deps) const override;
 
 protected:
diff --git a/mlir/include/mlir/Analysis/DataFlowFramework.h b/mlir/include/mlir/Analysis/DataFlowFramework.h
index 0d766dffc77e9..0dff75f0f488f 100644
--- a/mlir/include/mlir/Analysis/DataFlowFramework.h
+++ b/mlir/include/mlir/Analysis/DataFlowFramework.h
@@ -34,12 +34,18 @@ class DataFlowAnalysis;
 // AnalysisDependencies
 //===----------------------------------------------------------------------===//
 
-/// Helper used by `DataFlowAnalysis::getDependentAnalyses` to declare the
-/// analyses that must be loaded into the solver for an analysis to run
-/// correctly. Declared analyses are not auto-loaded by the solver; callers
-/// are expected to load them explicitly with the appropriate constructor
-/// arguments. `DataFlowSolver::initializeAndRun` fails with a diagnostic if
-/// any declared dependency is missing.
+/// Collection of sibling analyses a `DataFlowAnalysis` subclass declares it
+/// requires via `DataFlowAnalysis::getDependentAnalyses`. The solver consults
+/// it at `initializeAndRun` time and errors out if any declared analysis is
+/// missing from the solver.
+///
+/// Declared analyses are *not* auto-loaded by the solver. `DataFlowSolver::
+/// load<T>` can take arbitrary constructor arguments that the framework
+/// cannot synthesize, so the caller retains control of how each analysis is
+/// instantiated; this class only captures the contract. Use hard
+/// dependencies sparingly, and only for analyses that are strictly required
+/// for correctness; analyses that would merely improve precision should be
+/// loaded explicitly by the pipeline author instead.
 ///
 /// Dependencies are matched by `TypeID`. Analyses defined inside an
 /// anonymous namespace must therefore provide an explicit TypeID via
@@ -383,8 +389,10 @@ class DataFlowSolver {
   /// Initialize the children analyses starting from the provided top-level
   /// operation and run the analysis until fixpoint.
   ///
-  /// Fails with a diagnostic if any child analysis declares a dependency via
-  /// `DataFlowAnalysis::getDependentAnalyses` that has not been loaded.
+  /// Returns failure if any child analysis fails during initialization or
+  /// fixpoint iteration, or if dependency validation fails (a child analysis
+  /// declares a dependency via `DataFlowAnalysis::getDependentAnalyses` that
+  /// has not been loaded).
   LogicalResult initializeAndRun(Operation *top);
 
   /// Lookup an analysis state for the given lattice anchor. Returns null if one
@@ -682,13 +690,15 @@ class DataFlowAnalysis {
   /// necessarily identical under the corresponding lattice type.
   virtual void initializeEquivalentLatticeAnchor(Operation *top) {}
 
-  /// Register the analyses that this analysis depends on. Each dependency
-  /// must be loaded into the solver before `initializeAndRun` is called.
+  /// Register the analyses that this analysis depends on. Each declared
+  /// dependency must be loaded into the solver (via `DataFlowSolver::load`)
+  /// before `initializeAndRun`; otherwise `initializeAndRun` fails with a
+  /// diagnostic listing the missing dependencies.
   ///
-  /// Dependencies are not auto-loaded, because `DataFlowSolver::load` accepts
-  /// arbitrary constructor arguments that the framework cannot synthesize.
-  /// Subclasses that override this method should call the parent's
-  /// `getDependentAnalyses` first to preserve inherited dependencies.
+  /// Subclasses that override this method should chain to the parent's
+  /// `getDependentAnalyses` so that dependencies inherited from base classes
+  /// are preserved. Declarations are deduplicated, so the order of calls
+  /// does not matter.
   virtual void getDependentAnalyses(AnalysisDependencies &deps) const {}
 
   /// Return the TypeID of this analysis. Valid only after
diff --git a/mlir/lib/Analysis/DataFlowFramework.cpp b/mlir/lib/Analysis/DataFlowFramework.cpp
index a1a97097c36d9..667a2a3485bc7 100644
--- a/mlir/lib/Analysis/DataFlowFramework.cpp
+++ b/mlir/lib/Analysis/DataFlowFramework.cpp
@@ -111,8 +111,8 @@ Location LatticeAnchor::getLoc() const {
 // DataFlowSolver
 //===----------------------------------------------------------------------===//
 
-/// Emit a diagnostic listing all analyses whose declared dependencies are not
-/// loaded in the solver. Returns failure if any dependency is missing.
+/// Emits a diagnostic listing all analyses whose declared dependencies are
+/// not loaded in the solver. Returns failure if any dependency is missing.
 static LogicalResult
 validateDependencies(Operation *top,
                      ArrayRef<std::unique_ptr<DataFlowAnalysis>> analyses) {



More information about the Mlir-commits mailing list