llvm / llvm/llvm-project

[MLIR][Affine] Miscompilation: `--affine-super-vectorize` writes past the iteration space when the trip count is not a multiple of the vector size

Open
#218,120 2 comments 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
memref.global "private" @start : memref<8xi32> = dense<[1, 2, 3, 4, 5, 6, 7, 8]>
func.func private @printMemrefI32(memref<*xi32>)

func.func @main() {
%g = memref.get_global @start : memref<8xi32>
%m = memref.alloc() : memref<8xi32>
memref.copy %g, %m : memref<8xi32> to memref<8xi32>

// Six iterations, over a buffer of eight. Elements 6 and 7 are not touched.
affine.for %j = 0 to 6 {
%v = affine.load %m[%j] : memref<8xi32>
%w = arith.addi %v, %v : i32
affine.store %w, %m[%j] : memref<8xi32>
}

%u = memref.cast %m : memref<8xi32> to memref<*xi32>
call @printMemrefI32(%u) : (memref<*xi32>) -> ()
return
}
```

### To reproduce

**Correct:**
```
mlir-opt small.mlir --lower-affine --convert-vector-to-scf --convert-scf-to-cf \
--convert-vector-to-llvm --expand-strided-metadata --finalize-memref-to-llvm \
--convert-func-to-llvm --convert-ub-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:
```
Unranked Memref base@ = 0xaaab023eee00 rank = 1 offset = 0 sizes = [8] strides = [1] data =
[2, 4, 6, 8, 10, 12, 7, 8]
```

**Wrong:**
```
mlir-opt small.mlir --affine-super-vectorize=virtual-vector-size=4 \
--lower-affine --convert-vector-to-scf --convert-scf-to-cf \
--convert-vector-to-llvm --expand-strided-metadata --finalize-memref-to-llvm \
--convert-func-to-llvm --convert-ub-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:
```
Unranked Memref base@ = 0xaaaaf738afc0 rank = 1 offset = 0 sizes = [8] strides = [1] data =
[2, 4, 6, 8, 10, 12, 14, 16]
```

The loop doubles elements 0 through 5. Elements 6 and 7 keep their input values `7` and `8` without the pass, and are doubled to `14` and `16` with it.

Contributor guide

Open the contributing guide

Research direction

Start by running the provided small.mlir reproducer with and without --affine-super-vectorize=virtual-vector-size=4, then compare the printed buffers. The fix is complete when the transformed loop preserves elements 6 and 7 for the six-iteration trip count, and the reproducer reports [2, 4, 6, 8, 10, 12, 7, 8].

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
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.