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

    <tr>
        <th>Summary</th>
        <td>
            Clang misses obfuscated `and`-`or` function optimization, where GCC is able to
        </td>
    </tr>

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

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

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

<pre>
    ```c++
bool func1(bool a, bool b, bool c) {
    return !((!a & !b & !c) | (!a & b & !c) | (a & !b & !c));
}

bool func2(bool a, bool b, bool c) {
 return !((!a && !b && !c) || (!a && b && !c) || (a && !b && !c));
}
```
`func1` uses bitwise `and` and `or`
`func2` uses conditional `and` and `or`
Both returning `a and b or c`.
Given these 2 functions, this is what x86-64 clang (trunk) `-O3` generated:
```asm
func1(bool, bool, bool):                            # @func1(bool, bool, bool)
        mov     eax, edi
        or      al, dl
        mov     ecx, eax
        or      cl, sil
        not cl
        not     al
        and     al, sil
        or      al, cl
        or      sil, dl
        not     sil
        and     sil, dil
        or      al, sil
        not     al
        and     al, 1
        ret

func2(bool, bool, bool):                            # @func2(bool, bool, bool)
        mov     eax, edi
        test    edi, edi
        jne     .LBB1_4
        test    sil, sil
        jne .LBB1_4
        test    dl, dl
        jne     .LBB1_4
        xor eax, eax
        ret
.LBB1_4:
        xor     al, sil
 xor     al, 1
        or      al, dl
        ret
```
For both functions, it is not able to see through the function as `a and b or c`.
However, x86-64 GCC (trunk) `-O3` is able to for `func1`, as shown below:
```asm
func1(bool, bool, bool):
        and     esi, edi
 mov     eax, esi
        or      eax, edx
 ret

func2(bool, bool, bool):
        mov     eax, edx
 test    dil, dil
        jne     .L8
        test    sil, sil
 jne     .L8
.L4:
        ret
.L8:
        cmp     sil, 1
 jne     .L9
        test    dil, dil
        je      .L4
.L9:
 xor     edi, 1
        or      dil, sil
        cmovne  eax, edi
        ret
```
(all test are done via godbolt)
Thanks.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJykVs2OozgQfhrnUkpkG0LgwGGSVmYPI6202vvKQAU8TXDLNkl2n35lwl8IpKc1EZLBrq9-v6pYGCPzCjEm2z3Zvq1EbQul479Eju-yysNVorJ_YxLQ-5MSvncPfSP0W6JUCae6ShnhYfMhCD9A85b0bynhEZBdiwEA0GhrXQHhDtc8TADhgdtJupcWdoCxwOzpPNY9XmuU7N7al0e_-Rf8XnJ6bHvi3MT7PoB5sVfa5oPpitJ_3msRUKgNGkikvUqDQAIqqsxtiypzX0pPQbwHparKpJWqEuVL4F7Zos2JrPJGtJFKQGlISUA3d7nv8oIV2AINAm-S7pQbl2VbSAPSwLUQFm5hsA58SEvhtPHQ6rp6bxIU0PWfnnMixwq1sJgR79skA8Kc7ztjNnaVHNaIeA0Bl36Ee0B8-pmSnsjud1aXZkVxczKYycdzpe-raFRk5QI6vaPFbR6dNmgjJ_BKWXf0tNcafNh31RkceVL16OdUaXfqYDNhdDaftHZGO9xrq7PxfR4LezzUaMfdPm7036LEKyVfooRF04TlDubOf1bYrJsf-z37x58Htxl9SpkDvwRmsxV8afOmdB_MlKF9tjtk15xj8FyJH_fZV7pmqPDjCDwqDYkbTA9zRlo3ZRyVRFIiWAUGEWyhVZ0XbjT14iDM8iT7Q13xgtppbIfV98NhYVRJ09s6KQ2j0ezgwoAp1LWCBEt1_a1pNt8WaCbEmjLSLAypnrG34V_va730SSd0ensyLsyFgY7hL9L_CbH58czFEVnDp8P0_AEj1exJcbTQUEsx3HHgHGmNjjLU0b8dAgv8zxa6PD2ri_NracQsdYi7Z5Tl3XWhETJVIVykgFxliSptP8v-LkT1bjarLPayyIvECmMW7Dy2Y5FPV0VMeUq30SnYMc7CaJti4Pu7jLOUeWzrs3AlY065RxkNabSNKN14IWfhzguzk0jYdusTn-JZyHJTlpfzRul8JY2pMd5GYeitSpFgabpbqY6d0Dqpc0N8WkpjzQCz0pYYH5qbw1kad4tRyak2qbsrDJeYdXeBGdpdfVh5lv8J9-HSeC1QY9PWQwOval3GhbUfxtWOHwk_5tIWdbJJ1Znwo3OjXdYfWv3E1BJ-bEIxhB-baP4PAAD__66q8ok">