<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/92069>92069</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Inconsistent result with --sparsification-and-bufferization and tensor.empty
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
Anonymous15592
</td>
</tr>
</table>
<pre>
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
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWUtv2z4S_zT0ZWBDoiw_Dj6kSQME2L0sejcoaWSxoEgtScVxP_2ClGVLtvxqG6Bb_IFEtsjhcDjzmwfHzBi-kYgrEn8h8cuI1bZQevUkldyVqjZhHC_pKFHZbvWspOEZarAFQq6EUFsuN_Dvf739ByqtNpqVJHoiwQsJntikFFwfXsks2P_511JltUAg8y_NO0Bey3TiHkCmgUVplF7ziBK6IDRmehOQ6AmacRI9hx9uLvpK6BLGJPoKPKJdbgCExjz7CIBEL8Blhh-TVEljmbQQ9KgakobzBD-sZqmFds_4y54PiV9gWIIDL4221rJl-eREaifJ_GX_tXdM9xn6Ey7PhE_DtT9T9AJMc1scxQ9PuTf0wSX6M2n29Fdonb561HFPSWVld63YQzoBQl8JfYXaOHg05B1ufu6Uaa5VuUaBJUprege6qvS-waVBbTFb00WXdTPcUSqXVnkBGvum91iX0DgKPdeUCTEE0s7urWYIXVyFbJ99sLgAxcfk9Op9x9QqPak0l_YgexcFZwR-9xOcNJA-Q_HxS9-rm-ebhS0XAlRtq9qC3SrIeJ6jRmlBo6mFNbAtUAKrKrFzEOnTqMrykv9glisJFTMGDP63RpmiOY8nvfnwKJDTfvsyHpuKacNznnqmYyazcVK7_dptxuNGp4dhhPHY-WdvIFXyHbVtJqwaC_Fedoa93wyMN7ruTORcMsF_4LjEUmM-sMT7ZWdcY6pkygWOa6nRL87GKTPWnNpgUDH0kmL-llP757cC4RYw9rA0PofhB6a1ZYlAsAWzh7mQ0GfYFtyPIwhmLerDbDA5bteiNkVI0G4R5W0JmMwuEB3NBNw0ItkCNbo3JoFlGXdoZeIRbHc29uwgwQ2Xzu1U7t9vCTzpeTfktZMJmGRi96NR0N7VG34GvT-f-6xjH_66Y56Y3nGlN1B9ssQZrglETuTe8cOuBX5z9dLA_jOql4bzRCiWXS5dzrf_Y0qXR0oRJoRKu6f2A0dRmOAb6aoITzObNmxmUzK_qYY9Q2OVxuNBXCxo9z1NxFeYHYxzqV7Yy32oFK7Co8c3HDT6g_KdFgADtnkw_V9xK_qJbvXYpaCxSS_GTKxaN4pqnecO297nnoOWesA3j455Zp6jY_6_Xio-0ZNb7uvgUyNFqqrd0fc6cWJ9AUJg1a8FoHVwr4tfxnrjMDdlHQDypVAW_NSFh35GGKM3wtj9lxiDWO6LsN9UsIDVyPalp6pQu0LQ_dvhwNm7vnaqOAOGldjGvUPioEsPFC--v151t7mDLzeQOvkwg2R3Rt3c4odLwhzeQGMlWIr9gnJwLWy5Lc5ouvf_o0XoMygN32tjYatZdTd35mOiBzy4tFSqjOccs16vqn9NLbBRa2OITol_WHva4nosfW1Qrk_8Zu8XA_2T07j9YBx-rF0zVAfG10kvJZ-_t3F3T5L91Az7kz27NmQPwm8fsi8j8Wbb7g_sBX5mI_CfLuDdCRS2SmaogefHHoZRLm8VDglbrdyzlwoe6mV0myjXctS3gps2u3LpvIYbizLdQcl2IJWFBIG54J4ILCHBlNXmZpYxhapFBkqKHaRKWsZlk9dNUTEELnOly6bi6mplwy28ozbuKNET0HAWMZzPwkWwSFmA8XS-iOJ5tJjmsyxLWJoinS8xGWWrKFtGSzbCVTgP49ksDqPFqFglNJnHs2CxQEbjWZDSRTrNglkwi0OWh5iP-IoGdBrE4TSIo0W8mNCEMpzGMbI8CREpmQZYMi4mQryXE6U3I25MjaslDWbLkWAJCuN_GqJU4hb8JKGUxC8jvXJrxkm9MWQaCG6sOXKx3ApcvR0V3vZ-G5vfUUj5yqij_FGtxaqwtvIXSA_wDbdFnUxSVRL66rbef4wrrb5jagl99QIbQl_9gf4XAAD__-ZywhQ">