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

    <tr>
        <th>Summary</th>
        <td>
            [InstCombine] Generalise `((x1 ^ y1) | (x2 ^ y2)) == 0` transform to more than two pairs of variables 
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            llvm:optimizations,
            llvm:instcombine,
            missed-optimization
      </td>
    </tr>

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

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

<pre>
    InstCombine currently recognises `((x1 ^ y1) | (x2 ^ y2)) == 0` as an idiom for `x1 == y1 && x2 == y2`, but this idiom detection does not work when more than 2 pairs of variables are being compared:

This function
```c
bool xor2(uint64_t x1, uint64_t y1, uint64_t x2, uint64_t y2) {
    return ((x1 ^ y1) | (x2 ^ y2)) == 0;
}
```
is simplified to 
```
define i1 @xor2(i64 %0, i64 %1, i64 %2, i64 %3) {
  %5 = icmp eq i64 %0, %1
  %6 = icmp eq i64 %2, %3
  %7 = and i1 %5, %6
  ret i1 %7
}
```

But these two functions are not:
```c
bool xor3(uint64_t x1, uint64_t y1, uint64_t x2, uint64_t y2, uint64_t x3,
          uint64_t y3) {
    return ((x1 ^ y1) | (x2 ^ y2) | (x3 ^ y3)) == 0;
}

bool xor4(uint64_t x1, uint64_t y1, uint64_t x2, uint64_t y2, uint64_t x3,
          uint64_t y3, uint64_t x4, uint64_t y4) {
    return ((x1 ^ y1) | (x2 ^ y2) | (x3 ^ y3) | (x4 ^ y4)) == 0;
}
```
```
define i1 @xor3(i64 %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5) {
  %7 = xor i64 %1, %0
  %8 = xor i64 %3, %2
  %9 = or i64 %8, %7
  %10 = xor i64 %5, %4
  %11 = or i64 %9, %10
  %12 = icmp eq i64 %11, 0
  ret i1 %12
}

define i1 @xor4(i64 %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5, i64 %6, i64 %7) {
  %9 = xor i64 %1, %0
  %10 = xor i64 %3, %2
  %11 = or i64 %10, %9
  %12 = xor i64 %5, %4
  %13 = or i64 %11, %12
  %14 = xor i64 %7, %6
  %15 = or i64 %13, %14
  %16 = icmp eq i64 %15, 0
  ret i1 %16
}
```
[godbolt](https://godbolt.org/z/ojdexqrYP)
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy9VkuT2ygQ_jXShcqUeOh10CEz3t3ayiWHXPa0hQy2SSRwAGXs_Po0SLZl2dnZSVJRYRm6P31NvyRaI47N39r5J9O3Sku0HqyV2ndHZOXabLVy0qGkyBJSwThglOR_oCNOSI2S8gkFGRllBGRRTFcwUAYPIe4Q10gJZXq0MTYQBYoRcYQZKWCgQDHJSLT1hNrBI79TbnpYSC_XXhmNhIENaePRs7Gf0PNOatQbKwEMlgjac2UdMhv0hVvF2w7AHLStVHqL1qbfw0ok9G2SrZJsun8IdjaDjgYmRZGNYz2uW2M6dDAWnKwGpX3B_vXogMNOz8vj9fJArrVkjNnjSIjgstIPVqMfCC2dWJJytdjvuAR_nOr3ndooKZA36C5KyE1IuQLLLJucUwUDy3nMwTTHszmZzenCIRDlYYtIrfs9kp_RnCvyXIDFPSCZgHQGLCOQaxG3CRYmTHHCQBAnVfnfMRnvj7GupIOCeTbnpI9FAlV1qYzvFAD9qQKYa4Hp6VIL43UBL4P7ymo5y-gooy9X0JWb7Pe5OQezayr264NwlrFRxl7bWi_0EH11D53nbDbPb3tr7AQwccUZ7VxA1RJEJxCZgaK36IKpJkw5w-BsyXTqPDZH4QVVfer1-aYwudftOO4_u-1jTO6W5jLS7JdF-jwvZvPyNgP1_8nAbeDupeAmcPj0lqxvA_dSEuiS67QvfGWSLcnK5bs0oPIl2Wn7-Mrm3Rc4zr-X0uKFpsoft0a0pvNJvoK87rzfu_AuJn_CmFQPxm5h9RV-5qOQh8_2n_eQpFQ2uChoQQhmdSoaKmpa89Qr38kGiGenGyBHf0ktLe_gXPPjxxpvuXZwnunDp_Vy-ghflDvnj3SwXbPwSPnd0D7AeQQWXffl9Pdmb81HOOjAUjk3SAeTvKwoTneNqJhoM4oxxYLl6w2XOdnIvAquV3mN0463snPB5YSQSErfmr1XvfrK40cOxGMuT1oFoVlPoTnrerAsxZv5k0GZr1LVkIyQrMY1wThn9QOreLmpRAkhJ6ISOTSm7LnqHgJ_SFdqm-hWO2wdKCHq3l2U3Dm11TJmKfDzwe-Mbd71kn9SOo0RaKL73wAYib1z">