[MLIR] Add StoreLikeInterface to decouple activity analysis from stores#2978
Open
vchuravy wants to merge 11 commits into
Open
[MLIR] Add StoreLikeInterface to decouple activity analysis from stores#2978vchuravy wants to merge 11 commits into
vchuravy wants to merge 11 commits into
Conversation
wsmoses
reviewed
Jul 22, 2026
vchuravy
commented
Jul 23, 2026
vchuravy
commented
Jul 23, 2026
vchuravy
force-pushed
the
worktree-active-store-interface
branch
from
July 23, 2026 07:48
ef1e602 to
139bc9e
Compare
Pangoraw
reviewed
Jul 23, 2026
Pangoraw
approved these changes
Jul 23, 2026
Pangoraw
left a comment
Collaborator
There was a problem hiding this comment.
maybe could be implemented for affine.store as well?
Member
|
ci err |
wsmoses
reviewed
Jul 23, 2026
| // | ||
| // This is the memref analogue of the affine.store `@if_then` test. | ||
| // | ||
| // XFAIL: * |
Member
Author
There was a problem hiding this comment.
Yeah, planning on it, I just wanted to have a test first.
wsmoses
reviewed
Jul 23, 2026
| // This is the llvm.store analogue of the affine.store `@if_then` test. | ||
| // | ||
| // XFAIL: * | ||
| // FIXME: forward-mode differentiation of llvm.store does not currently emit the |
…s deps
Two dialect-agnostic, non-Fortran registration changes, factored out so they can
land independently of the FIR/HLFIR autodiff work that motivated them.
* Move registerCoreDialectAutodiffInterfaces (the aggregate that force-links
every core-dialect autodiff model, Linalg/NVVM included) out of
CoreDialectsAutoDiffImplementations.cpp into a dedicated translation unit,
CoreDialectsAutoDiffRegistration.cpp. That old TU also defines the
memory-identity handler the FIR/HLFIR models depend on, so anything linking
those models used to drag in the whole aggregate. Isolating it lets a
consumer that only wants a subset of dialects (e.g. a lean `flang -fc1`
plugin that must not pull in Linalg symbols flang does not export) link the
individual register*DialectAutoDiffInterface entry points and never reference
the aggregate TU.
* Drop the stale linalg and tensor entries from the `enzyme` / `enzyme-wrap`
pass dependentDialects. Neither pass creates linalg ops; tensor is only
needed for vector-mode concat and every in-tree tool registers it itself.
These were the last undefined dialect symbols that blocked dlopen'ing the
plugin against a host that does not export Linalg/Tensor TypeIDs.
No behavior change for the existing tools (enzymemlir-opt still calls the
aggregate). Full MLIR suite green except the 2 pre-existing LLVM-24 failures
(complex_create_im, affine_parallel_mincut).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BkvJByk8nTti2GiF4RudNG
- Restore tensor::TensorDialect in the `enzyme` pass dependentDialects (Passes.td) and the DifferentiatePass registry.insert override (EnzymeMLIRPass.cpp). The pass batches scalar ops into tensors by default (ArithConstantOpBatchInterface), so tensor must be loaded. Only the stale linalg entry is dropped. - Remove the explanatory NOTE comment left where registerCoreDialectAutodiffInterfaces used to live. - Add trailing newline to CoreDialectsAutoDiffRegistration.cpp. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…stores Activity analysis hard-codes which ops are stores (dyn_cast<LLVM::StoreOp> / memref::StoreOp) when reasoning about stored-value / pointer activity. That prevents out-of-tree dialects from participating and duplicates logic per dialect. Add enzyme::ActiveStoreOpInterface exposing (getStoredValue, getStoredPointer), attach it to memref.store and llvm.store, and use it at the potential-active- store site that already handled both dialects -- now a single dialect-agnostic branch. Any dialect (e.g. an out-of-tree fir.store / hlfir.assign) can opt in by attaching the interface. Behavior-preserving: llvm.store/memref.store return the same value/pointer through the interface. The MLIR test suite is unchanged (the two ReverseMode failures are pre-existing on this LLVM build, independent of this change). The remaining LLVM-specific store sites (which walk llvm.alloca / llvm.load origins) are intentionally left as-is. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Address review: rename the interface and clarify getStoredPointer's description to note it returns the base pointer before any in-op offsets. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extends the StoreLikeInterface generalization to the remaining store sites in ActivityAnalysis and gates the pointer-like type check on the type interface, so out-of-tree dialects (e.g. FIR/HLFIR) participate fully in activity analysis without hard-coded dyn_casts. These are the Fortran-independent pieces of #2969. - isConstantValue: besides LLVM ptr / memref, treat any type whose AutoDiffTypeInterface reports isMutable() (e.g. !fir.ref) as a reference that carries active memory. Behavior-preserving in-tree: among core dialects only memref and LLVM pointer report isMutable(), and both are already matched by the existing isa<> check. - isOperationInactiveFromOrigin: dialect-agnostic store branch mirroring the LLVM::StoreOp case (inactive iff stored value or pointer is constant). - isValueActivelyStoredOrReturned: dialect-agnostic store branch mirroring the LLVM::StoreOp case. Deliberately excludes the Fortran-coupled / behavior-changing parts of #2969 (FIR/HLFIR models, flang plugin, the CoreDialects registration TU split, and dropping tensor/linalg from the pass dependent dialects). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Paul Berg <naydex.mc+github@gmail.com>
Lets activity analysis reason about affine.store's stored-value/pointer activity generically, the same way memref.store and llvm.store now do, instead of requiring a hard-coded dyn_cast. getStoredPointer returns the base memref (the affine map's indices are applied within the op). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The affine.store `@if_then` test in ForwardMode/affine.mlir covers a memref that is unconditionally initialized with a constant and then conditionally overwritten with an active value: forward mode must zero-initialize the shadow before the conditional store, otherwise the not-taken path reads uninitialized shadow memory and returns a garbage tangent instead of 0. No equivalent coverage existed for memref.store or llvm.store. Add memref_if.mlir and llvm_if.mlir as the direct analogues. Both are marked XFAIL: forward-mode differentiation of memref.store / llvm.store does not currently emit the shadow zero-initialization, so the tests document the known bug and will XPASS once it is fixed. Verified with a local enzymemlir-opt build: FileCheck fails on exactly the zero-init CHECK-DAG line and matches everywhere else. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
vchuravy
force-pushed
the
worktree-active-store-interface
branch
from
July 23, 2026 15:48
c27d97a to
4858baa
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Activity analysis currently hard-codes which ops are stores (
dyn_cast<LLVM::StoreOp>/memref::StoreOp) when reasoning about stored-value / pointer activity. That prevents out-of-tree dialects from participating and duplicates the same logic per dialect.Change
enzyme::ActiveStoreOpInterfacewithgetStoredValue()/getStoredPointer().memref.storeandllvm.store.ActivityAnalysis.cppthat already handled both dialects — now a single dialect-agnostic branch.Any dialect can now opt into store-activity handling by attaching the interface (e.g. an out-of-tree
fir.store/hlfir.assign), without touching the core analysis.Behavior
Behavior-preserving:
llvm.store/memref.storereturn the same value/pointer through the interface as the hard-coded accessors did. The remaining LLVM-specific store sites (which recurse throughllvm.alloca/llvm.loadorigins) are intentionally left as-is.The MLIR test suite is unchanged: 135/137 pass, and the 2
ReverseModefailures are pre-existing on this LLVM build (they fail identically without this change).Motivation
This is a standalone extract from the Enzyme⇄Flang HLFIR work (#2969): it lets
fir.store/hlfir.assignparticipate in activity analysis so by-reference Fortran differentiates, while keepingAnalysis/free of any FIR/HLFIR dependency.🤖 Generated with Claude Code