<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/59838>59838</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [mlir] affine-loop-invariant-code-motion and affine-pipeline-data-transfer Incorrect behavior
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          lipracer
      </td>
    </tr>
</table>

<pre>
    ```
#map = affine_map<(d0)[s0, s1] -> (d0 * 163840 + s0 * 20480 + s1 * 320)>
#set = affine_set<() : (-1 >= 0)>

func.func private @cluster_id() -> index
func.func private @core_id() -> index
func.func @main(%arg0: memref<10485760xi32>, %arg1: memref<1xi32>, %arg2: memref<10485760xi32>) {
  %c10485760 = arith.constant 10485760 : index
  %c320 = arith.constant 320 : index
 %c0 = arith.constant 0 : index
  %c1 = arith.constant 1 : index
  %0 = memref.alloc() {alignment = 16 : i64} : memref<0xi32, 2>
  %1 = memref.alloc() : memref<1xi32, 2>
  %3 = call @core_id() : () -> index
 %4 = call @cluster_id() : () -> index
  affine.for %arg3 = 0 to 64 {
 %5 = affine.apply #map(%arg3)[%4, %3]
    %6 = memref.alloc() {alignment = 16 : i64} : memref<0xi32, 2>
    %7 = memref.alloc() : memref<320xi32, 2>
    affine.dma_start %arg0[%5], %7[%c0], %6[%c0], %c320 : memref<10485760xi32>, memref<320xi32, 2>, memref<0xi32, 2>
 affine.dma_start %arg1[%c0], %1[%c0], %0[%c0], %c1 : memref<1xi32>, memref<1xi32, 2>, memref<0xi32, 2>
    affine.dma_wait %6[%c0], %c320 : memref<0xi32, 2>
    affine.dma_wait %0[%c0], %c1 : memref<0xi32, 2>
 %8 = affine.apply #map(%arg3)[%4, %3]
    %9 = memref.alloc() {alignment = 16 : i64} : memref<0xi32, 2>
    %10 = memref.alloc() : memref<320xi32, 2>
    affine.for %arg4 = 0 to 320 {
      %11 = affine.load %7[%arg4] : memref<320xi32, 2>
      %2 = affine.load %1[0] : memref<1xi32, 2>
 %12 = arith.addi %11, %2 : i32
      %13 = arith.addi %12, %11 : i32
      affine.store %13, %10[%arg4] : memref<320xi32, 2>
    }
 affine.dma_start %10[%c0], %arg2[%8], %9[%c0], %c320 : memref<320xi32, 2>, memref<10485760xi32>, memref<0xi32, 2>
    affine.dma_wait %9[%c0], %c320 : memref<0xi32, 2>
  }
  return
}
```
when I run command with:```./bin/mlir-opt  -affine-pipeline-data-transfer -mlir-print-ir-after-all test_pipeline.mlir```
I got:
```
#map = affine_map<(d0)[s0, s1] -> (d0 * 163840 + s0 * 20480 + s1 * 320)>
#map1 = affine_map<(d0) -> (d0 - 1)>
#map2 = affine_map<(d0) -> (d0 mod 2)>
module {
  func.func private @cluster_id() -> index
  func.func private @core_id() -> index
  func.func @main(%arg0: memref<10485760xi32>, %arg1: memref<1xi32>, %arg2: memref<10485760xi32>) {
    %c64 = arith.constant 64 : index
    %c0 = arith.constant 0 : index
 %c10485760 = arith.constant 10485760 : index
    %c320 = arith.constant 320 : index
    %c0_0 = arith.constant 0 : index
    %c1 = arith.constant 1 : index
    %0 = call @core_id() : () -> index
    %1 = call @cluster_id() : () -> index
    %alloc = memref.alloc() : memref<2x320xi32, 2>
    %alloc_1 = memref.alloc() : memref<2x1xi32, 2>
    %alloc_2 = memref.alloc() : memref<2x0xi32, 2>
    %alloc_3 = memref.alloc() : memref<2x0xi32, 2>
    %2 = affine.apply #map(%c0)[%1, %0]
    affine.dma_start %arg0[%2], %alloc[%c0 mod 2, 0], %alloc_2[%c0 mod 2, 0], %c320 : memref<10485760xi32>, memref<2x320xi32, 2>, memref<2x0xi32, 2>
    affine.dma_start %arg1[%c0_0], %alloc_1[%c0 mod 2, 0], %alloc_3[%c0 mod 2, 0], %c1 : memref<1xi32>, memref<2x1xi32, 2>, memref<2x0xi32, 2>
 affine.for %arg3 = 1 to 64 {
      %9 = affine.apply #map(%arg3)[%1, %0]
      affine.dma_start %arg0[%9], %alloc[%arg3 mod 2, 0], %alloc_2[%arg3 mod 2, 0], %c320 : memref<10485760xi32>, memref<2x320xi32, 2>, memref<2x0xi32, 2>
      affine.dma_start %arg1[%c0_0], %alloc_1[%arg3 mod 2, 0], %alloc_3[%arg3 mod 2, 0], %c1 : memref<1xi32>, memref<2x1xi32, 2>, memref<2x0xi32, 2>
      %10 = affine.apply #map1(%arg3)
      %11 = affine.apply #map2(%10)
      %12 = affine.apply #map2(%10)
      %13 = affine.apply #map2(%10)
      %14 = affine.apply #map2(%10)
 affine.dma_wait %alloc_2[%10 mod 2, 0], %c320 : memref<2x0xi32, 2>
 affine.dma_wait %alloc_3[%10 mod 2, 0], %c1 : memref<2x0xi32, 2>
      %15 = affine.apply #map(%10)[%1, %0]
      %alloc_6 = memref.alloc() {alignment = 16 : i64} : memref<0xi32, 2>
      %alloc_7 = memref.alloc() : memref<320xi32, 2>
      affine.for %arg4 = 0 to 320 {
        %16 = affine.load %alloc[%10 mod 2, %arg4] : memref<2x320xi32, 2>
        %17 = affine.load %alloc_1[%10 mod 2, 0] : memref<2x1xi32, 2>
        %18 = arith.addi %16, %17 : i32
        %19 = arith.addi %18, %16 : i32
 affine.store %19, %alloc_7[%arg4] : memref<320xi32, 2>
      }
 affine.dma_start %alloc_7[%c0_0], %arg2[%15], %alloc_6[%c0_0], %c320 : memref<320xi32, 2>, memref<10485760xi32>, memref<0xi32, 2>
 affine.dma_wait %alloc_6[%c0_0], %c320 : memref<0xi32, 2>
    }
    %3 = affine.apply #map1(%c64)
    %4 = affine.apply #map2(%3)
    %5 = affine.apply #map2(%3)
    %6 = affine.apply #map2(%3)
    %7 = affine.apply #map2(%3)
    affine.dma_wait %alloc_2[%3 mod 2, 0], %c320 : memref<2x0xi32, 2>
    affine.dma_wait %alloc_3[%3 mod 2, 0], %c1 : memref<2x0xi32, 2>
    %8 = affine.apply #map(%3)[%1, %0]
    %alloc_4 = memref.alloc() {alignment = 16 : i64} : memref<0xi32, 2>
    %alloc_5 = memref.alloc() : memref<320xi32, 2>
    affine.for %arg3 = 0 to 320 {
 %9 = affine.load %alloc[%3 mod 2, %arg3] : memref<2x320xi32, 2>
 %10 = affine.load %alloc_1[%3 mod 2, 0] : memref<2x1xi32, 2>
      %11 = arith.addi %9, %10 : i32
      %12 = arith.addi %11, %9 : i32
 affine.store %12, %alloc_5[%arg3] : memref<320xi32, 2>
    }
 affine.dma_start %alloc_5[%c0_0], %arg2[%8], %alloc_4[%c0_0], %c320 : memref<320xi32, 2>, memref<10485760xi32>, memref<0xi32, 2>
 affine.dma_wait %alloc_4[%c0_0], %c320 : memref<0xi32, 2>
 memref.dealloc %alloc_3 : memref<2x0xi32, 2>
    memref.dealloc %alloc_2 : memref<2x0xi32, 2>
    memref.dealloc %alloc_1 : memref<2x1xi32, 2>
 memref.dealloc %alloc : memref<2x320xi32, 2>
    return
 }
}
```

Obviously, scalar types should not be double buffered. I think it is because there is no loop invariant promotion.
``` affine.dma_start %arg1[%c0_0], %alloc_1[%c0 mod 2, 0], %alloc_3[%c0 mod 2, 0], %c1 : memref<1xi32>, memref<2x1xi32, 2>, memref<2x0xi32, 2>```
but when I run with:
```./bin/mlir-opt -affine-loop-invariant-code-motion -affine-pipeline-data-transfer -mlir-print-ir-after-all test_pipeline.mlir```
I got:
```
#map = affine_map<(d0)[s0, s1] -> (d0 * 163840 + s0 * 20480 + s1 * 320)>
#map1 = affine_map<(d0) -> (d0 - 1)>
#map2 = affine_map<(d0) -> (d0 mod 2)>
module {
  func.func private @cluster_id() -> index
  func.func private @core_id() -> index
 func.func @main(%arg0: memref<10485760xi32>, %arg1: memref<1xi32>, %arg2: memref<10485760xi32>) {
    %c64 = arith.constant 64 : index
    %c0 = arith.constant 0 : index
    %c10485760 = arith.constant 10485760 : index
    %c320 = arith.constant 320 : index
    %c0_0 = arith.constant 0 : index
    %c1 = arith.constant 1 : index
    %alloc = memref.alloc() {alignment = 16 : i64} : memref<0xi32, 2>
    %alloc_1 = memref.alloc() : memref<1xi32, 2>
    %0 = call @core_id() : () -> index
    %1 = call @cluster_id() : () -> index
    %2 = affine.load %alloc_1[0] : memref<1xi32, 2>
    %alloc_2 = memref.alloc() : memref<2x320xi32, 2>
    %alloc_3 = memref.alloc() : memref<2x0xi32, 2>
    %3 = affine.apply #map(%c0)[%1, %0]
    affine.dma_start %arg0[%3], %alloc_2[%c0 mod 2, 0], %alloc_3[%c0 mod 2, 0], %c320 : memref<10485760xi32>, memref<2x320xi32, 2>, memref<2x0xi32, 2>
 affine.for %arg3 = 1 to 64 {
      %8 = affine.apply #map(%arg3)[%1, %0]
      affine.dma_start %arg0[%8], %alloc_2[%arg3 mod 2, 0], %alloc_3[%arg3 mod 2, 0], %c320 : memref<10485760xi32>, memref<2x320xi32, 2>, memref<2x0xi32, 2>
      %9 = affine.apply #map1(%arg3)
      %10 = affine.apply #map2(%9)
      %11 = affine.apply #map2(%9)
 affine.dma_start %arg1[%c0_0], %alloc_1[%c0_0], %alloc[%c0_0], %c1 : memref<1xi32>, memref<1xi32, 2>, memref<0xi32, 2>
      affine.dma_wait %alloc_3[%9 mod 2, 0], %c320 : memref<2x0xi32, 2>
      affine.dma_wait %alloc[%c0_0], %c1 : memref<0xi32, 2>
      %12 = affine.apply #map(%9)[%1, %0]
      %alloc_6 = memref.alloc() {alignment = 16 : i64} : memref<0xi32, 2>
      %alloc_7 = memref.alloc() : memref<320xi32, 2>
 affine.for %arg4 = 0 to 320 {
        %13 = affine.load %alloc_2[%9 mod 2, %arg4] : memref<2x320xi32, 2>
        %14 = arith.addi %13, %2 : i32
        %15 = arith.addi %14, %13 : i32
        affine.store %15, %alloc_7[%arg4] : memref<320xi32, 2>
      }
      affine.dma_start %alloc_7[%c0_0], %arg2[%12], %alloc_6[%c0_0], %c320 : memref<320xi32, 2>, memref<10485760xi32>, memref<0xi32, 2>
      affine.dma_wait %alloc_6[%c0_0], %c320 : memref<0xi32, 2>
    }
    %4 = affine.apply #map1(%c64)
    %5 = affine.apply #map2(%4)
    %6 = affine.apply #map2(%4)
    affine.dma_start %arg1[%c0_0], %alloc_1[%c0_0], %alloc[%c0_0], %c1 : memref<1xi32>, memref<1xi32, 2>, memref<0xi32, 2>
 affine.dma_wait %alloc_3[%4 mod 2, 0], %c320 : memref<2x0xi32, 2>
 affine.dma_wait %alloc[%c0_0], %c1 : memref<0xi32, 2>
    %7 = affine.apply #map(%4)[%1, %0]
    %alloc_4 = memref.alloc() {alignment = 16 : i64} : memref<0xi32, 2>
    %alloc_5 = memref.alloc() : memref<320xi32, 2>
    affine.for %arg3 = 0 to 320 {
      %8 = affine.load %alloc_2[%4 mod 2, %arg3] : memref<2x320xi32, 2>
      %9 = arith.addi %8, %2 : i32
      %10 = arith.addi %9, %8 : i32
 affine.store %10, %alloc_5[%arg3] : memref<320xi32, 2>
    }
 affine.dma_start %alloc_5[%c0_0], %arg2[%7], %alloc_4[%c0_0], %c320 : memref<320xi32, 2>, memref<10485760xi32>, memref<0xi32, 2>
 affine.dma_wait %alloc_4[%c0_0], %c320 : memref<0xi32, 2>
 memref.dealloc %alloc_3 : memref<2x0xi32, 2>
    memref.dealloc %alloc_2 : memref<2x320xi32, 2>
    return
  }
}
```
```Afine.load``` appears before in the ```dma_start```, this is obviously incorrect. When I find the source code and find that the processing here is marked as ```FIXME```, can we do a simple memory effects analysis to handle this problem? If so, I will submit a patch.

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsW0tv4zgS_jX0pWBDJCXbOviQRwfIYbHH3VtASVTMHUkUSDrp_PuFJMvWg3rYTmYyPQ0MMmmKVSySxY9ffVKY1uI143yHvHvkPS7Yweyl2iUiVyzkahHI6GOH1s7xP-cROXeI0JTlgOgjsDgWGX9JWY7oAyLbyEHER969dhB5AI2R9whLRH9A-QwQuQO8plu3-PUedNVCHHd7bMBlAyWlG_rjNJ7mpjme5qYaDxEfEL0r3C8xFBb0EdrG5c_4kIWr4gfkSrwxwwG5TpgctOHqRURHT2WkIov4zzErqfgcE-Q6KRNZ2c9j6tUp4kx5qniM6AN23K23WTs_BSVFrOQBqm643a33nIy78QFt7qtQoLAI6x7V8ilh9qtQZtqwzEDj2V1zEpUlJVajqrndv-hu7TzgGlujsfat3FYTXrEkkWG97Zt7lojXLOVZlRt4XTlYu2jzCK1lqtaHPAA55UXpHA86729C35qW1iFLkn5eHJPSliKFqds27SbimPXxDKxiqY4pUcXhgJGwdhv7j4jnNU7NiuV58gHV6T2lJa0ObBHTMcko8h7rscp5rr9sC0r3m1mbQMmAh-PkopS9aMOUgfq4lZPyislU89pULaFzblr3m8I6v8eO6mBUzWe2eAeCxf04LE2OJVpsS9VOIPiiENtL-s6Emb1S893NmIrNGSLe9jMy2v_ajMbDoHVJSp9PuHs-4eWinyG-HhE3lyWRLGpkfOGguIjnDV76IzZ3RUo6PUc2dCw6kwbGsygSVZjHHSHVqlLSnQe1WZH6TGCb2TFKbaTilY-6u3PN_NHmceSwYkvmlrdy2bo9N_pzDswYfIzBzvyDNisM-_V4WgdQ3BxUduRTdXOHFL7veQbPoA4ZhDJNWRbBuzB7RM8dV4g8BQUjekoToZYyNwDLKuZlLnKeFL9EzLClUSzTMVewLHvmSmRmKdSSxYarZXFrGq7NS220Knp14nmGV2mK0W3B_gUMNmU5Hh6wOcQScN-WzLNNZQSkaZ3K6JDwJmJcR4WH7EbJcNPoG9DhinuuXRv5LFs77BMu4bXXc-2L2XYd2Mtcyn0Z6W7Q7su5LTR49XX0tnRQ3pmzLlHycxjJj35e5tF88tNK9Bt-yEw_U_HQm_2QcRYUOicOhM_k8XEuaSaNu62M7niH1PDyAE6nxwsZ7XMZqe5vafvpZYXAiUi_9ILGMyZGxyc2h393E2t6NgMlHu6VeNAitPNYsT0jpnLCt-ZEGdpkVgz2-lPy4obMmJgenZre12QHtMsMy67j9raP1QpNM1KZYcdiNIg4Y0b0GiP3AiML421lHp6LR6PnsO-ejrvHM5G8mvCESIOnwLxxs3ylVNMY5kbJ5uIKt1qnta0obYBRczeGyr4RulAPsxkcpoaF7rbP5BH1AFtbjbuui9aNrcatDH2b4bY2XHcMe3Wx3wKva8WB0fK45boDrKcqGXtdIF3bDL62XB482jNjmVQPoKERD0N0uHZbEHjShofxj3YNBvFjyGB9qcHmIoMpUJ7LBeYwPSssz7uNx_j1hMo4RaZOAblfKzRWg3ifrDbSISzuEk0LBtMuBNPZENxjNFbspVdCb4P4tPDTP4mFQ5LkqJDpT4EuaQGdd2aMn6VIthwPQe62i7juN0LcmbHYfB6TPuJHwaBZYc856kP25Eb7HtTY8nLAeDZhacqy5yQZEmirn_8O3oQ86OSjVDdDljAF5iPnGvReHpIIMmkg4BDJQ5BwCA5xzBWPVvAMZi-yP0AYEBoCHrKD5mD2XPGiIZOQSJmDyN6YEiwzkCuZSiNktuqE82sU6u3FDQ4GGgp4rXy3J27Rv2v5u1i75WntlqGM-LJavd8K-S-tkP9zBHK45XuUb6mRj4vUn0jwbvhM5TuI-daXyWdgn_dK-RodfvrNwO1K_GCB9ylKPL1MZ591E3655nqxen3JNx3Xqdc9_julTM8UeP8c_XpM4B-XegcV4mPh7l8hD_tW-fVSJtd7ZC0CvuTzpmkBwb9VoRgeYs40R9XiiVd__i8lFl-lE9Ph-4b09vcGodi1CQP1x0fWL5xaen_brv5WDVO7YU9Y8D5XzR0G0VmSbveV8V8h6Y4f7c_VdQdF2mFdd0qm7RlMybTukOr6d8HiKRh2v-Tl3Q0IPCaFN_bkn6cMW5mcFXrd6wXiDhdq4ed2DHYbTMiq_W6nRFznW4i4m98i7m0i7jwldYaUWv_z7pTnDXUzzzlTGgIeF-kjMjB7Dqfnp20_-yQPYPZCg9Aga3kWRBZKpXhoVvCfSliMRRaVvrQ8qJBDKCMOLIvqB8yUT3MlQ661yF6hFmdTpv7gETB9DuPp-b__-tEKIWQZvHOIJDDQIs0TXiydVB_A45iHRgPLWPKhhS6O_55lUcKruHMlg4SniD7BcwxaFt6e4V0kCehDkAoDDHJmwv1RCV5EOxr51GcLvsPrDfGxg_F2sd9Rx3FcEgc4cFlItxt_TQKH4S2j8TqKt3QhdsQh1MGO5_jYw9sVdQMnDj3ieX7sbEmMXIenTCSrJHlLV1K9LoTWB77z_C3dLhIW8ESXf-pGSMbfoXyISEFeFmpX2CyDw6tGrpMIbfTZixEmKf9GrtRRvRrixnTbYmfGpdvneosh4Hv2JqRaHFSy2xuTa0TvEHlC5OlVmP0hWIUyReSpiOf4v2Wu5P94aBB5KmehEXkqZ_n_AAAA__9cb8oy">