)]}'
{
  "commit": "777ceded34617370d43dbed00f3ee79de493f1c2",
  "tree": "595cf051c209a8af0fdb22128b96f7887af327ec",
  "parents": [
    "4964ebe26335822fde24682f154eeb3c8f6e73a6"
  ],
  "author": {
    "name": "Valentin Churavy",
    "email": "v.churavy@gmail.com",
    "time": "Mon Jul 27 00:58:11 2026 +0200"
  },
  "committer": {
    "name": "GitHub",
    "email": "noreply@github.com",
    "time": "Sun Jul 26 22:58:11 2026 +0000"
  },
  "message": "[MLIR] Add StoreLikeInterface to decouple activity analysis from stores (#2978)\n\n* [MLIR] Add ActiveStoreOpInterface to decouple activity analysis from stores\n\nActivity analysis hard-codes which ops are stores (dyn_cast\u003cLLVM::StoreOp\u003e /\nmemref::StoreOp) when reasoning about stored-value / pointer activity. That\nprevents out-of-tree dialects from participating and duplicates logic per\ndialect.\n\nAdd enzyme::ActiveStoreOpInterface exposing (getStoredValue, getStoredPointer),\nattach it to memref.store and llvm.store, and use it at the potential-active-\nstore site that already handled both dialects -- now a single dialect-agnostic\nbranch. Any dialect (e.g. an out-of-tree fir.store / hlfir.assign) can opt in by\nattaching the interface.\n\nBehavior-preserving: llvm.store/memref.store return the same value/pointer\nthrough the interface. The MLIR test suite is unchanged (the two\nReverseMode failures are pre-existing on this LLVM build, independent of this\nchange). The remaining LLVM-specific store sites (which walk llvm.alloca /\nllvm.load origins) are intentionally left as-is.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com\u003e\n\n* [MLIR] Rename ActiveStoreOpInterface to StoreLikeInterface\n\nAddress review: rename the interface and clarify getStoredPointer\u0027s\ndescription to note it returns the base pointer before any in-op offsets.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com\u003e\n\n* [MLIR] Finish dialect-agnostic activity analysis for stores/mutable refs\n\nExtends the StoreLikeInterface generalization to the remaining store sites\nin ActivityAnalysis and gates the pointer-like type check on the type\ninterface, so out-of-tree dialects (e.g. FIR/HLFIR) participate fully in\nactivity analysis without hard-coded dyn_casts. These are the\nFortran-independent pieces of EnzymeAD/Enzyme#2969.\n\n- isConstantValue: besides LLVM ptr / memref, treat any type whose\n  AutoDiffTypeInterface reports isMutable() (e.g. !fir.ref) as a reference\n  that carries active memory. Behavior-preserving in-tree: among core\n  dialects only memref and LLVM pointer report isMutable(), and both are\n  already matched by the existing isa\u003c\u003e check.\n- isOperationInactiveFromOrigin: dialect-agnostic store branch mirroring\n  the LLVM::StoreOp case (inactive iff stored value or pointer is constant).\n- isValueActivelyStoredOrReturned: dialect-agnostic store branch mirroring\n  the LLVM::StoreOp case.\n\nDeliberately excludes the Fortran-coupled / behavior-changing parts of\n#2969 (FIR/HLFIR models, flang plugin, the CoreDialects registration TU\nsplit, and dropping tensor/linalg from the pass dependent dialects).\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com\u003e\n\n* Cleanup PR a bit\n\n* apply clang-format\n\n* Update enzyme/Enzyme/MLIR/Interfaces/AutoDiffOpInterface.td\n\nCo-authored-by: Paul Berg \u003cnaydex.mc+github@gmail.com\u003e\n\n* [MLIR] Attach StoreLikeInterface to affine.store\n\nLets activity analysis reason about affine.store\u0027s stored-value/pointer\nactivity generically, the same way memref.store and llvm.store now do,\ninstead of requiring a hard-coded dyn_cast. getStoredPointer returns the\nbase memref (the affine map\u0027s indices are applied within the op).\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com\u003e\n\n* [MLIR] Add forward-mode conditional-store tests for memref/llvm\n\nThe affine.store `@if_then` test in ForwardMode/affine.mlir covers a memref\nthat is unconditionally initialized with a constant and then conditionally\noverwritten with an active value: forward mode must zero-initialize the shadow\nbefore the conditional store, otherwise the not-taken path reads uninitialized\nshadow memory and returns a garbage tangent instead of 0.\n\nNo equivalent coverage existed for memref.store or llvm.store. Add memref_if.mlir\nand llvm_if.mlir as the direct analogues. Both are marked XFAIL: forward-mode\ndifferentiation of memref.store / llvm.store does not currently emit the shadow\nzero-initialization, so the tests document the known bug and will XPASS once it\nis fixed.\n\nVerified with a local enzymemlir-opt build: FileCheck fails on exactly the\nzero-init CHECK-DAG line and matches everywhere else.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com\u003e\n\n* fix constant handling\n\n* clang format\n\n* [MLIR] Zero shadow memory for inactive stores in forward mode\n\nRestore the original store-inactivity condition in activity analysis: a\nstore is inactive if *either* the stored value or the pointer is inactive,\nmatching LLVM Enzyme\u0027s isInstructionInactiveFromOrigin.\n\nThat condition alone made the shadow store disappear, because\nMGradientUtils::visitChild skips any constant operation in forward mode, so\nmemoryIdentityForwardHandler never ran and never emitted the null value it\nalready knows how to produce for a constant operand. LLVM Enzyme has no such\ngate: its forward-mode visitCommonStore returns early only when the pointer\nis constant. Mirror that by continuing to visit store-like ops whose pointer\nis active.\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n\n* [MLIR] Address review: generalize the forward-mode skip condition\n\nReplace the store-specific storesThroughActivePointer check with the general\ncondition wsmoses suggested: only skip a constant operation in forward mode if\nit is pure, or if all of its operands are constant. A side-effecting op with an\nactive operand may still need to touch shadow memory, which now also covers\nllvm.memcpy / llvm.memset rather than only StoreLikeInterface ops. This also\nmakes the stale /*iface.hasNoEffect()*/ note redundant.\n\nRetain the \"if we are being stored into, not storing this value\" comment in\nisValueActivelyStoredOrReturned.\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com\u003e\nCo-authored-by: Paul Berg \u003cnaydex.mc+github@gmail.com\u003e",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "fdbbeeb6f434e77c2dbaf83a0087751c7e42232a",
      "old_mode": 33188,
      "old_path": "enzyme/Enzyme/MLIR/Analysis/ActivityAnalysis.cpp",
      "new_id": "ff97b213c468faab2c14f87616c86d5e0c5aa41f",
      "new_mode": 33188,
      "new_path": "enzyme/Enzyme/MLIR/Analysis/ActivityAnalysis.cpp"
    },
    {
      "type": "modify",
      "old_id": "da8b531b4a8f2a71366fe00565be34fa48d7556a",
      "old_mode": 33188,
      "old_path": "enzyme/Enzyme/MLIR/Implementations/AffineAutoDiffOpInterfaceImpl.cpp",
      "new_id": "dbf2185465d1e5e8a239283f8feca4aed22f7a3c",
      "new_mode": 33188,
      "new_path": "enzyme/Enzyme/MLIR/Implementations/AffineAutoDiffOpInterfaceImpl.cpp"
    },
    {
      "type": "modify",
      "old_id": "e4b8f370dd2ff559446c0851e9e1b4d6d7bbff3f",
      "old_mode": 33188,
      "old_path": "enzyme/Enzyme/MLIR/Implementations/CoreDialectsAutoDiffRegistration.cpp",
      "new_id": "06132501ddcca3bfe372dce31a5c0ebc02e246b4",
      "new_mode": 33188,
      "new_path": "enzyme/Enzyme/MLIR/Implementations/CoreDialectsAutoDiffRegistration.cpp"
    },
    {
      "type": "modify",
      "old_id": "3b45d636cedc8fd1e60b43ba0e5bb45227167e77",
      "old_mode": 33188,
      "old_path": "enzyme/Enzyme/MLIR/Implementations/LLVMAutoDiffOpInterfaceImpl.cpp",
      "new_id": "d76469c86861e37375fd6ac7d4511307cb413254",
      "new_mode": 33188,
      "new_path": "enzyme/Enzyme/MLIR/Implementations/LLVMAutoDiffOpInterfaceImpl.cpp"
    },
    {
      "type": "modify",
      "old_id": "ffbf3952c16599c825c90378d080588cd07c5fb0",
      "old_mode": 33188,
      "old_path": "enzyme/Enzyme/MLIR/Implementations/MemRefAutoDiffOpInterfaceImpl.cpp",
      "new_id": "2427bf98627b9e2eab71f4945c962ae354827eb5",
      "new_mode": 33188,
      "new_path": "enzyme/Enzyme/MLIR/Implementations/MemRefAutoDiffOpInterfaceImpl.cpp"
    },
    {
      "type": "modify",
      "old_id": "81c76f61a8ad4d79a656fa87c05941292eab994a",
      "old_mode": 33188,
      "old_path": "enzyme/Enzyme/MLIR/Interfaces/AutoDiffOpInterface.td",
      "new_id": "f3df11ce677627d917c7b09998346e43bc1a225c",
      "new_mode": 33188,
      "new_path": "enzyme/Enzyme/MLIR/Interfaces/AutoDiffOpInterface.td"
    },
    {
      "type": "modify",
      "old_id": "9c98b684570d0f935ce9021d947be0aee2b6cc94",
      "old_mode": 33188,
      "old_path": "enzyme/Enzyme/MLIR/Interfaces/GradientUtils.cpp",
      "new_id": "a7a1088b1bc90761e337b88377a39996ffa27f22",
      "new_mode": 33188,
      "new_path": "enzyme/Enzyme/MLIR/Interfaces/GradientUtils.cpp"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "b869d02a0397ece1d5115f6cb7559b2a9160d62e",
      "new_mode": 33188,
      "new_path": "enzyme/test/MLIR/ForwardMode/llvm_if.mlir"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "ceff1514f19bc7d74ff846c5fe22e2af1bdc90de",
      "new_mode": 33188,
      "new_path": "enzyme/test/MLIR/ForwardMode/memref_if.mlir"
    }
  ]
}
