[MLIR][Affine] `affine-data-copy-generate` emits a copy that reads a memref defined later
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
The pass chooses where to start copying by finding the first affine memory operation in the block, and inserts the generated copy-in nests there. Nothing checks where the memrefs accessed in that range are defined, so when a `memref.get_global` sits after the first `affine.load`, the copy generated for it is placed before its own operand.
## Reproducer
### small.mlir
```mlir
memref.global "private" constant @g1 : memref<8xi64> = dense<[0, 1, 2, 3, 4, 5, 6, 7]>
memref.global "private" constant @g2 : memref<8xi64> = dense<[7, 6, 5, 4, 3, 2, 1, 0]>
func.func @f(%s: index, %t: index) -> i64 {
%a = memref.get_global @g1 : memref<8xi64>
%x = affine.load %a[symbol(%s)] : memref<8xi64>
%b = memref.get_global @g2 : memref<8xi64>
%y = affine.load %b[symbol(%t)] : memref<8xi64>
%r = arith.addi %x, %y : i64
return %r : i64
}
```
### To reproduce:
```
$ mlir-opt small.mlir -o /dev/null
(input parses and verifies)
$ mlir-opt small.mlir -pass-pipeline='builtin.module(func.func(affine-data-copy-generate))' -o /dev/null
small.mlir:11:8: error: operand #0 does not dominate this use
%y = affine.load %b[symbol(%t)] : memref<8xi64>
^
small.mlir:11:8: note: see current operation: %13 = "affine.load"(%16, %arg1) <{map = affine_map<()[s0] -> (s0)>}> : (memref<8xi64>, index) -> i64
small.mlir:10:8: note: operand defined here (op in the same block)
%b = memref.get_global @g2 : memref<8xi64>
^
```
### Actual Output:
```
error: operand #0 does not dominate this use
```
### Expected Output:
```
(the pass either generates copies or declines; the module still verifies)
```
Contributor guide
Assessment
This issue has not been assessed yet.