)]}'
{
  "commit": "b059222ae7eef1a572e035a4e9ba816fe37f876a",
  "tree": "ddd7c51f007df6fd7c50c8f0fb25f354a1770303",
  "parents": [
    "5af287e24bf2870174599b04af866a2bd8531ec7"
  ],
  "author": {
    "name": "Hao Ren",
    "email": "123687754+moomoohorse321@users.noreply.github.com",
    "time": "Wed May 27 18:26:37 2026 -0500"
  },
  "committer": {
    "name": "GitHub",
    "email": "noreply@github.com",
    "time": "Wed May 27 16:26:37 2026 -0700"
  },
  "message": "[Codegen] Use default read semantics for LinalgExt scatter (#24504)\n\nThe original impl. will introduce critical but very subtle bugs. We\nidentified the bug when running Qwen-3.5, with decode-prefill-decode\npattern. Because of the problem detailed below, the 2nd decode are\ncompletely wrong.\n\n## Problem\n\n`iree_linalg_ext.scatter` **was** special-cased in the LinalgExt\nbufferization\nexternal model as not reading its DPS init operand which is not correct.\n\n\n  ## Fix\n\n  Remove the ScatterOp-specific no-read override and use the default\n  DestinationStyleOpInterface bufferization read semantics.\n\nAfter this change, out-of-place bufferization preserves the init value\nbefore\n  scatter updates it:\n```\n  alloc tmp[32][1][512]\n  copy original -\u003e tmp // which was previously dropped.\n  scatter writes 11 rows into tmp\n```\n\n\n  ### Minimal Repro\n\nA simple overwrite scatter still needs to preserve elements that are not\nupdated:\n\n  ```text\nresult \u003d original // this was incorrectly dropped if it\u0027s not fixed with\nthe config shown in test cases attached\n  for i in updated_indices:\n    result[i] \u003d update[i]\n```\n\n  Example shape:\n\n  original: 32 x 1 x 512\n  updates : 11 x 1 x 512\n  indices : 11 rows\n  result  : 32 x 1 x 512\n\n  Scatter writes only 11 rows. The remaining 21 rows must come from original.\n\n  **Before this change, bufferization thinks `outs(%original)` as a destination\n  placeholder instead of a read. So it stores tmp[32][1][512] to output**\n\n### Analysis\n\nI propose that we remove the override because scatter op should be bufferized as reads except for some small corner cases. Overriding the scatter op does not preserve correctness.\n\nLet\u0027s analyze the following cases for scatter:\n\n  - `updates` is read: scatter must read the update value.\n  - `indices` is read: scatter must read indices to know where to write.\n  - `mask`, if present, is read: a false mask suppresses the update and preserves\n    the original value.\n  - DPS init / original is read:\n    - elements not hit by `indices` must be inherited from original;\n    - masked-off updates must preserve original;\n    - the combiner region may use the old value, e.g. `yield update + old`;\n    - `unique_indices(false)` combine/reduction-style scatter also needs the\n      old/current value.\n\n  The only case where init may not need to be read is a separately proven\n  full-overwrite optimization: indices cover the entire result, mask cannot\n  suppress updates, and the combiner does not use the old value. That should be\n  handled by a dedicated copy-elision/full-overwrite analysis, not by the default\n  bufferization semantics.\n\n  ## Tests\n\n  Added LLVMGPU bufferization tests for:\n\n  - overwrite scatter preserving original;\n  - combiner scatter reading original;\n  - masked scatter preserving original.\n\nSigned-off-by: Yuwei Sun \u003cyuweis2@illinois.edu\u003e\nSigned-off-by: Hao Ren \u003crhao8608@gmail.com\u003e\nCo-authored-by: Hao Ren \u003crhao8608@gmail.com\u003e\nCo-authored-by: Yuwei Sun \u003cyuweis2@illinois.edu\u003e",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "9fe37d624e7fad07edb839985cf0079b5f87c6ca",
      "old_mode": 33188,
      "old_path": "compiler/src/iree/compiler/Codegen/Interfaces/BufferizationInterfaces.cpp",
      "new_id": "ee5f80077e3c5027d6d02cff3f1f64a026dba8f6",
      "new_mode": 33188,
      "new_path": "compiler/src/iree/compiler/Codegen/Interfaces/BufferizationInterfaces.cpp"
    },
    {
      "type": "modify",
      "old_id": "d8844d4567b4c8fe4feafae2a3457b26513fd134",
      "old_mode": 33188,
      "old_path": "compiler/src/iree/compiler/Codegen/LLVMGPU/test/llvmgpu_bufferize.mlir",
      "new_id": "ab0048adcb0d25339dde16dfb5cd6146ec45e83c",
      "new_mode": 33188,
      "new_path": "compiler/src/iree/compiler/Codegen/LLVMGPU/test/llvmgpu_bufferize.mlir"
    }
  ]
}
