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

    <tr>
        <th>Summary</th>
        <td>
            [mlir] createOrFold does not sort commutative constant operands before trying to fold
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            mlir
      </td>
    </tr>

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

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

<pre>
    Reproduction commit is found here: https://github.com/llvm/llvm-project/commit/0f099162404e89abfbd605d4bfbbe5a3bee494cc. Output of test case displayed below.

Expected behaviour:
Commutative operations should switch the constant operations to the second operand before trying to fold.

Problem:
spirv.IMul and spirv.IAdd are commutative operations, as such it is assumed that a constant operand should be positioned as the second operand when folding. In the reproduction we lower from MemRef.load to SPIR-V and there is the possibility to fold away a spirv.IMul 1 x -> x and spirv.IAdd 0 x -> x by invoking createOrFold. However, in the reproduction we see that the constant operands are not placed in the second position, and so they do not match the pattern to fold. Further, if we manually switch the order of the operands at the createOrFold we have the desired behaviour that the folding occurs.

>From brief inspection, it does appear that the commutative implementation of the fold is being invoked.

```
mlir-opt -split-input-file -convert-memref-to-spirv="bool-num-bits=8" -cse commutative-folding.mlir
%cst1_i32 = spirv.Constant 1 : i32 <------------------- IMul.getOperand1()
%0 = unrealized_conversion_cast %arg1 : index to i32    <------------------- IMul.getOperand2()

%cst0_i32_0 = spirv.Constant 0 : i32 <------------------- IAdd.getOperand1()
%2 = spirv.IMul %0, %cst1_i32 : i32    <------------------- IAdd.getOperand2()

module attributes {spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [Shader, Int64], [SPV_KHR_storage_buffer_storage_
class]>, #spirv.resource_limits<>>} {
 func.func @load_i16(%arg0: memref<10xi16, #spirv.storage_class<StorageBuffer>>, %arg1: index) -> i16 {
    %0 = builtin.unrealized_conversion_cast %arg0 : memref<10xi16, #spirv.storage_class<StorageBuffer>> to !spirv.ptr<!spi
rv.struct<(!spirv.array<5 x i32, stride=4> [0])>, StorageBuffer>
    %1 = builtin.unrealized_conversion_cast %arg1 : index to i32
    %cst0_i32 = spirv.Constant 0 : i32
    %cst1_i32 = spirv.Constant 1 : i32
    %2 = spirv.IMul %1, %cst1_i32 : i32 <-------------- operands are sorted AFTER fold is applied
    %3 = spirv.IAdd %2, %cst0_i32 : i32 <-------------- operands are sorted AFTER fold is applied
    %cst2_i32 = spirv.Constant 2 : i32
    %4 = spirv.SDiv %3, %cst2_i32 : i32
    %5 = spirv.AccessChain %0[%cst0_i32, %4] : !spirv.ptr<!spirv.struct<(!spirv.array<5 x i32, stride=4> [0])>, StorageBuf
fer>, i32, i32
    %6 = spirv.Load "StorageBuffer" %5 : i32
    %cst16_i32 = spirv.Constant 16 : i32
    %7 = spirv.UMod %3, %cst2_i32 : i32
    %8 = spirv.IMul %7, %cst16_i32 : i32
    %9 = spirv.ShiftRightArithmetic %6, %8 : i32, i32
    %cst65535_i32 = spirv.Constant 65535 : i32
    %10 = spirv.BitwiseAnd %9, %cst65535_i32 : i32
    %11 = spirv.ShiftLeftLogical %10, %cst16_i32 : i32, i32
    %12 = spirv.ShiftRightArithmetic %11, %cst16_i32 : i32, i32
    %13 = builtin.unrealized_conversion_cast %12 : i32 to i16
    return %13 : i16
  }
}

```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy0V1Fv4joW_jXmxQpKHALlgQcKRXe0M5pRu3tfkWOfEO8mdmSfQNlfv7ITIGnp7VSrW1W0wfY53_edzyc2d04dNMCKZI8k2054i6WxK6VzqJSY5EaeV8_QWCNbgcpoKkxdK6TK0cK0WtISLJB0TUvExpF0TdiOsN1BYdnmU2FqwnZVdbz8iRpr_g0CCdt1gQjbxUW8XCZzNotn8LDkeZHLeZzJWV7kOWQ8zQFmy5kQU_qzxaZFagqK4JAK7oBK5ZqKn0HSHCpzmpJ4S-J19_n02oDAMFTyozKt9QDD0MbUdYsc1RGoacByT85RV5q2ktSdFIqSYglUGO2QaxzOQhOGHAijZTegfZLCWKBoz0of_JzCVHKE55c1eQX1FYRrlD1Ov_1oK-oD9I9rKSm3EJR-D5GwDeWOulaUtKsDd66tQVIsOVL-BrAP23HKgTbGKR8EpA9xh8KpBB1gK32Y0m86zLHD8p-AVuYElhbW1PQH1M9QTCvDpSf88uvbc_Rn4ILeFx6dj9AY51SuKoXniy6Un_iZcjqQIKGvNCLpE319q0Z8G8nPVOmj-Y-XWFjgCD_tzutM_zAnOIL1-qj7wB1AJ9L7umrpgubaIG0qLkBegvQKXaQL8nt0wQJnKk1YU_OLXxqOCFZf6093rfViBFyFh1Fz3fKqOg9dZqwEG4xdwgBRD3XA0wco-RHCgASn7NDeN3p9EakRorVu5MKdr1xuFRRUaed3SM9LIZUGHOVNA9wOpboZUdVNBTVoDG68IA4VVY7m4HOGAsHY-mQe97_hsa6UjUyDNHJNpTBSumkxKlQFNBJGH8FiVENtoYjQRMEKJN0SxnJjqki3dZQrdCTdPhDGaCTcCGV0sbBP0-dnmXCY7FXKKEm3vbs2FxMk1PewbnATvf-h3qHTA-DPrjYJYQ-ELa-x4xC01RZ4pf4Lct-RcMroveAOKWEZt4c-jZbw6g3i81H6mynZKOWAVOxJ7eN7tOJPaa2l_AtaQ63CHvVUvVXGcq4_YzLOcodJbWRbAeWIVuUtgqNk8djlRW4PgHvQxwCGsPTt9yTdXL89CiDp5phMO5jZ40vJZbf7vmmcz0i2vQz8-nP_jz-e9w6N5QfY521RgL0-drhExZ3za9KnjnafxoIzrRWwr1QdjLjxM9Insth65N1iWrRaTP0HJbPYN8m9SuaBvDdD7IXrTE7STRK_hsFBkguUDkS6eemeHwPQPl9XC2-tq7MIW3bdUiXzARhfnotR81ZVqPT0U8N2Bvo_QXqrE5Z08xu0oV7-sUMWgthWYPj-4TqTW8vPJN1k9NX7y2d1aJUEkm5nPizJHuNQz2WvxLvcQ-bJ15i_36qjaJd995e77u2Kz9vPaMW93Zd8tPvebb3xi80Z6w9C690_n56v7Zo3TaVAjpKmw6T-5euB3JLGf0tS4ZB9pA27q81sMPVlq44B-g0mG8IcLcwGC9dCgHObkivddbbsccCyj-ZbRoh018J_h3k7vL2F_Xu5W_-WyXzA5Ls_gRHGxjuAsQvj-3acf-jH-d01i8Hcf_0w8rdFf7jj5MXAyfMPVy6HdS5Vgc_qUOLaKixrQCWCEH2kh2uEO2oJh_MsS7OPKIfBuxCS4av1UeFJOVjrQH554zAMfidG8pbHdyjwuzkowbt9HX8oxx0yCfsNWZLkSyHTL_TH5NYCfG9M5rdQFrC1-hpxPRwli23_0r_-Mz4cTuQqlct0ySewShZJnLEsXSaTcpUsiyTLeFZwgDxlxUzwJE8TPi_mWb4o4olasZjN4jTJkkU2T5MpxFkKicyXMoN4kS7JLIaaq2rqr6FTYw8T5VwLq4dsNosnFc-hcuESzFg4NTLmr8N2FW6teXtw_hWuHLpbAFRYhYtzWJBtxwf1cJT2dwPfBUdn6PdXj7tXx0lrq9WXr9WBlSNsF4j9LwAA__-BUNTy">