Issue 92069
Summary Inconsistent result with --sparsification-and-bufferization and tensor.empty
Labels new issue
Assignees
Reporter Anonymous15592
    Consider the following MLIR program:
a.mlir:
```
module {
  func.func @tensor_i32(%arg0: tensor<1xi32>) -> i32 {
    %idx0 = index.constant 0
    %0 = tensor.extract %arg0[%idx0] : tensor<1xi32>
    return %0 : i32
  }
 func.func @func1() {
    %c1_i32 = arith.constant 1 : i32
    %c0_i32 = arith.constant 0 : i32
    %c0 = arith.constant 0 : index
    %5 = tensor.empty() : tensor<1xi32> // using empty
    // %5 = tensor.from_elements %c0_i32 : tensor<1xi32>
    
    %inserted_28 = tensor.insert %c1_i32 into %5[%c0] : tensor<1xi32>
    %31 = call @tensor_i32(%inserted_28) : (tensor<1xi32>) -> i32
    %308 = tensor.extract %5[%c0] : tensor<1xi32>
    // vector.print %31 : i32
 vector.print %308 : i32
    return
  }
}
```

It will output two different results when applying two different optimization pass sequences:
```pass sequence1```: ```--sparsification-and-bufferization --tensor-bufferize --func-bufferize --convert-func-to-llvm --convert-index-to-llvm --convert-vector-to-llvm --finalize-memref-to-llvm --convert-arith-to-llvm --reconcile-unrealized-casts```
```pass sequence2```: ```--tensor-bufferize --func-bufferize --convert-func-to-llvm --convert-index-to-llvm --convert-vector-to-llvm --finalize-memref-to-llvm --convert-arith-to-llvm --reconcile-unrealized-casts```

The ```pass sequence1``` outputs the executable that outputs 1, while the latter outputs 0.
The difference between ```pass sequence1``` and ```pass sequence2``` is that there is an additional ```--sparsification-and-bufferization``` at the begining of the ```pass sequence1```.

I futher analyze the output of these two sequences:
pass1: ```--sparsification-and-bufferization --tensor-bufferize```
pass2: ```--tensor-bufferize```
The result of ```pass1``` is:
```
module {
  func.func @tensor_i32(%arg0: memref<1xi32>) -> i32 {
    %idx0 = index.constant 0
    %0 = memref.load %arg0[%idx0] : memref<1xi32>
    return %0 : i32
  }
 func.func @func1() {
    %c1_i32 = arith.constant 1 : i32
    %c0 = arith.constant 0 : index
    %alloc = memref.alloc() {alignment = 64 : i64} : memref<1xi32>
    memref.store %c1_i32, %alloc[%c0] : memref<1xi32>
    %0 = call @tensor_i32(%alloc) : (memref<1xi32>) -> i32
    %1 = memref.load %alloc[%c0] : memref<1xi32>
    vector.print %1 : i32
    return
  }
}
```
The result of ```pass2``` is:
```
module {
  func.func @tensor_i32(%arg0: tensor<1xi32>) -> i32 {
    %0 = bufferization.to_memref %arg0 : memref<1xi32>
    %idx0 = index.constant 0
    %1 = memref.load %0[%idx0] : memref<1xi32>
 return %1 : i32
  }
  func.func @func1() {
    %c1_i32 = arith.constant 1 : i32
    %c0_i32 = arith.constant 0 : i32
    %c0 = arith.constant 0 : index
    %alloc = memref.alloc() {alignment = 64 : i64} : memref<1xi32>
    %alloc_0 = memref.alloc() {alignment = 64 : i64} : memref<1xi32>
    memref.copy %alloc, %alloc_0 : memref<1xi32> to memref<1xi32>
    memref.store %c1_i32, %alloc_0[%c0] : memref<1xi32>
 %0 = bufferization.to_tensor %alloc_0 : memref<1xi32>
    %1 = call @tensor_i32(%0) : (tensor<1xi32>) -> i32
    %2 = memref.load %alloc[%c0] : memref<1xi32>
    vector.print %2 : i32
    return
 }
}
```

It seems that ```--sparsification-and-bufferization --tensor-bufferize``` treats the operand and the result of ```tensor.insert``` as same tensor(memref), 
when the operand of ```tensor.insert``` is created by ```tensor.empty```.

If I replace the ```tensor.empty``` with ```tensor.from_element```, or just wrap the ```tensor.empty``` with a function. The modified MLIR program will output the same result.
The modified program:
```
module {
  func.func @gen_tensor_i32() -> tensor<1xi32> {
    %c0_i32 = arith.constant 0 : i32
    %5 = tensor.empty() : tensor<1xi32>
    return %5 : tensor<1xi32>
  }
  func.func @tensor_i32(%arg0: tensor<1xi32>) -> i32 {
    %idx0 = index.constant 0
    %0 = tensor.extract %arg0[%idx0] : tensor<1xi32>
    return %0 : i32
  }
  func.func @func1() {
 %c1_i32 = arith.constant 1 : i32
    %c0_i32 = arith.constant 0 : i32
 %c0 = arith.constant 0 : index
    %5 = call @gen_tensor_i32() : () -> tensor<1xi32>
    // %5 = tensor.empty() : tensor<1xi32> // using empty
    // %5 = tensor.from_elements %c0_i32 : tensor<1xi32>
    
 %inserted_28 = tensor.insert %c1_i32 into %5[%c0] : tensor<1xi32>
 %31 = call @tensor_i32(%inserted_28) : (tensor<1xi32>) -> i32
    %308 = tensor.extract %5[%c0] : tensor<1xi32>
    // vector.print %31 : i32
 vector.print %308 : i32
    return
  }
}
```

I wonder if there is some thing wrong with ```--sparsification-and-bufferization``` and ```tensor.empty```.
This result inconsistency may not be a problem because ```tensor.empty``` should only contains the shpae information.

git version: 2163ae761808ca0e5478357384f6ddbacce279eb
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to