)]}'
{
  "commit": "7fa390a7dc9aa0fd384448e172c18dee8b615a8b",
  "tree": "77be82478f1d84e547153e02e6e113a8c9c55441",
  "parents": [
    "7a2a6265c2945899fa8bfec15ef0291f18f3a718"
  ],
  "author": {
    "name": "William S. Moses",
    "email": "gh@wsmoses.com",
    "time": "Tue Aug 04 20:27:18 2026 -0500"
  },
  "committer": {
    "name": "William S. Moses",
    "email": "gh@wsmoses.com",
    "time": "Tue Aug 04 21:47:29 2026 -0500"
  },
  "message": "Keep the explicit cache decision for a loopy reduction\u0027s start value\n\ncomputeMinCache runs a min cut over Intermediates, then marks everything in\nthat set as recomputed or cached according to which side of the cut it landed\non:\n\n  knownRecomputeHeuristic[V] \u003d !MinReq.count(V);\n\nMembership of Intermediates therefore carries an invariant, established where\nthe set is built: a value only joins it if it is legal to recompute, since\nanything not selected by the cut will be. Values which are not legal to\nrecompute are excluded there, having already been given an explicit\nknownRecomputeHeuristic[V] \u003d false by the scan above.\n\npushLoopyPHIPreheader broke that invariant. Added in 04b80f67 to pull a loopy\nreduction\u0027s start value into the need graph, it inserted straight into\nIntermediates -- unconditionally, and after the cut had already been computed,\nso the value could never be selected for caching. For a start value that is\nnot legal to recompute, that overwrote a correct \"cache this\" decision with\n\"recompute this\", and computeMinCache then caught its own inconsistency:\n\n  Assertion `legalRecompute(V, Available2, nullptr)\u0027 failed.\n\nIn the reported case the start value is a load whose memory may be written\nbefore the reverse pass runs, so it must be cached.\n\nHave pushLoopyPHIPreheader collect the values instead, and let computeMinCache\napply the same legality gate the main worklist uses. A value that passes joins\nIntermediates as before; one that does not keeps the decision already made for\nit. Either way it is pushed onto the worklist, so the need graph is unchanged.\n\nFixes #3040\n\nCo-Authored-By: Claude Opus 5 (1M context) \u003cnoreply@anthropic.com\u003e\nClaude-Session: https://claude.ai/code/session_01P65yn8LELKWU1dq6AQvA5f\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "7510cf5920c542077461b23f41f0e78a1fc0ec70",
      "old_mode": 33188,
      "old_path": "enzyme/Enzyme/DifferentialUseAnalysis.cpp",
      "new_id": "9beefe5c0019850a031d29bde92633f84a1ce5b2",
      "new_mode": 33188,
      "new_path": "enzyme/Enzyme/DifferentialUseAnalysis.cpp"
    },
    {
      "type": "modify",
      "old_id": "17fb4a86beb0dfef09f8237cf3aceec6d4d346f9",
      "old_mode": 33188,
      "old_path": "enzyme/Enzyme/DifferentialUseAnalysis.h",
      "new_id": "dae104f75ce301f2b0205c5f0e6ce9b705643bb9",
      "new_mode": 33188,
      "new_path": "enzyme/Enzyme/DifferentialUseAnalysis.h"
    },
    {
      "type": "modify",
      "old_id": "9fec75e04d6130319fa5bb45fd668da6ad6e9f24",
      "old_mode": 33188,
      "old_path": "enzyme/Enzyme/GradientUtils.cpp",
      "new_id": "d847ed05213c39f0558bf1d9db3040fbaa8f6fa8",
      "new_mode": 33188,
      "new_path": "enzyme/Enzyme/GradientUtils.cpp"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "af0ed89f21f280297bc870ac0e30d5246c96a3ec",
      "new_mode": 33188,
      "new_path": "enzyme/test/Enzyme/ReverseMode/loopy-reduction-cached-preheader.ll"
    }
  ]
}
