llvm / llvm/llvm-project

[MLIR][SparseTensor] Miscompilation: `--sparsification-and-bufferization` hoists a written buffer out of a loop

Open
#218,091 1 comment 0 reactions 0 assignees View on GitHub
miscompilation mlir
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.