[MLIR][SparseTensor] Miscompilation: `--sparsification-and-bufferization` hoists a written buffer out of a loop
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
## Reproducer
### small.mlir
```mlir
func.func private @mlirfuzz_opaque_i64(i64) -> i64
func.func @g6(%a: i64, %cb: i64) -> i64 {
%i0 = index.constant 0
%i8 = index.constant 8
%i1 = index.constant 1
%i4 = index.constant 4
%start = index.casts %a : i64 to index
%r = scf.for %k = %i0 to %i8 step %i1 iter_args(%acc = %start) -> (index) {
%t = tensor.from_elements %a, %a, %a, %cb, %cb, %a, %a, %cb, %cb, %a, %a, %cb, %cb, %cb, %cb, %cb : tensor<4x4xi64>
%p = index.remu %k, %i4
%e = tensor.extract %t[%p, %p] : tensor<4x4xi64>
%q = index.remu %acc, %i4
%e0 = tensor.extract %t[%q, %q] : tensor<4x4xi64>
%u = tensor.from_elements %e0, %e0, %e0, %e0, %e0, %e0, %e0, %cb : tensor<8xi64>
%f = tensor.extract %u[%k] : tensor<8xi64>
%w = tensor.from_elements %cb, %e0, %e, %e0, %f, %e0, %f, %f : tensor<8xi64>
%s = index.remu %acc, %i8
%e4 = tensor.extract %w[%s] : tensor<8xi64>
%ins = tensor.insert %e4 into %t[%p, %p] : tensor<4x4xi64>
%e6 = tensor.extract %ins[%p, %p] : tensor<4x4xi64>
%n = index.castu %e6 : i64 to index
scf.yield %n : index
}
%out = index.castu %r : index to i64
return %out : i64
}
func.func @main() {
%ca = arith.constant -1 : i64
%cb = arith.constant -1992215323 : i64
%a = call @mlirfuzz_opaque_i64(%ca) : (i64) -> i64
%v = call @g6(%a, %cb) : (i64, i64) -> i64
vector.print %v : i64
return
}
```
### To reproduce
`$LLVM_LIB` is the `lib` directory of an `mlir-opt`/`mlir-runner` build; no other library is needed. The two commands differ in one pass and nothing else.
Correct:
```bash
mlir-opt small.mlir --inline --symbol-dce \
--one-shot-bufferize=bufferize-function-boundaries \
--lower-affine --convert-linalg-to-loops --buffer-deallocation-pipeline \
--convert-scf-to-cf --convert-vector-to-llvm --expand-strided-metadata \
--finalize-memref-to-llvm --convert-func-to-llvm --convert-index-to-llvm \
--convert-arith-to-llvm --convert-cf-to-llvm --reconcile-unrealized-casts \
| mlir-runner -e main --entry-point-result=void \
--shared-libs=$LLVM_LIB/libmlir_c_runner_utils.so,$LLVM_LIB/libmlir_runner_utils.so
```
Output:
```
-1
```
Wrong:
```bash
mlir-opt small.mlir --inline --symbol-dce \
--sparsification-and-bufferization \
--lower-affine --convert-linalg-to-loops --buffer-deallocation-pipeline \
--convert-scf-to-cf --convert-vector-to-llvm --expand-strided-metadata \
--finalize-memref-to-llvm --convert-func-to-llvm --convert-index-to-llvm \
--convert-arith-to-llvm --convert-cf-to-llvm --reconcile-unrealized-casts \
| mlir-runner -e main --entry-point-result=void \
--shared-libs=$LLVM_LIB/libmlir_c_runner_utils.so,$LLVM_LIB/libmlir_runner_utils.so
```
Output:
```
-1992215323
```
`--sparsifier` gives the same wrong answer, since it runs this pass.
Contributor guide
Research direction
Start with the small.mlir reproducer and run the two mlir-opt/mlir-runner pipelines, comparing the correct -1 output with the incorrect -1992215323 output. Then trace --sparsification-and-bufferization, also used by --sparsifier, to locate the buffer hoisting; done when this reproducer returns -1 without regressing the pipeline behavior.
Written by the indexing model from the issue text.
Assessment
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100