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

    <tr>
        <th>Summary</th>
        <td>
            Inefficient code generated in simple boolean expression
        </td>
    </tr>

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

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

    <tr>
      <th>Reporter</th>
      <td>
          jamescooper-blis
      </td>
    </tr>
</table>

<pre>
    In the code below, the function `check4` should return `true`.
It does not do this when using `&&`, but it does when using `&`.

```
static bool take4v1(bool a, bool b, bool c, bool d) {
    return (a && b) || (a && c) || (a && d);
}

static bool take4v2(bool a, bool b, bool c, bool d) {
    return a && (b || c || d); // Optimises better if & is used instead.
}

bool check4(bool a, bool b, bool c, bool d) {
    return take4v1(a, b, c, d) == take4v2(a, b, c, d);
}
```

LLVM IR generated in the problematic case (-std=c++17 -O3):
```
define dso_local noundef zeroext i1 @_Z6check4bbbb(i1 noundef zeroext %0, i1 noundef zeroext %1, i1 noundef zeroext %2, i1 noundef zeroext %3) local_unnamed_addr #0 !dbg !18 {
  call void @llvm.dbg.value(metadata i1 %0, metadata !22, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !26
  call void @llvm.dbg.value(metadata i1 %1, metadata !23, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !26
  call void @llvm.dbg.value(metadata i1 %2, metadata !24, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !26
  call void @llvm.dbg.value(metadata i1 %3, metadata !25, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !26
  call void @llvm.dbg.value(metadata i1 %0, metadata !27, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !33
  call void @llvm.dbg.value(metadata i1 %1, metadata !30, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !33
  call void @llvm.dbg.value(metadata i1 %2, metadata !31, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !33
  call void @llvm.dbg.value(metadata i1 %3, metadata !32, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !33
  %5 = or i1 %2, %3
  %6 = or i1 %5, %1, !dbg !35
  %7 = and i1 %6, %0, !dbg !35
  call void @llvm.dbg.value(metadata i1 %0, metadata !36, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !42
  call void @llvm.dbg.value(metadata i1 %1, metadata !39, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !42
  call void @llvm.dbg.value(metadata i1 %2, metadata !40, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !42
  call void @llvm.dbg.value(metadata i1 %3, metadata !41, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !42
  %8 = xor i1 %0, true, !dbg !44
  %9 = or i1 %8, %1, !dbg !44
  %10 = select i1 %9, i1 %0, i1 %5, !dbg !44
  %11 = xor i1 %10, %7, !dbg !45
  %12 = xor i1 %11, true, !dbg !45
  ret i1 %12, !dbg !46
}
 ```
 
 LLVM IR in the correct case (same flags):
 ```
define dso_local noundef zeroext i1 @_Z6check4bbbb(i1 noundef zeroext %0, i1 noundef zeroext %1, i1 noundef zeroext %2, i1 noundef zeroext %3) local_unnamed_addr #0 !dbg !18 {
  call void @llvm.dbg.value(metadata i1 %0, metadata !22, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !26
  call void @llvm.dbg.value(metadata i1 %1, metadata !23, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !26
  call void @llvm.dbg.value(metadata i1 %2, metadata !24, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !26
  call void @llvm.dbg.value(metadata i1 %3, metadata !25, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !26
  call void @llvm.dbg.value(metadata i1 %0, metadata !27, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !33
  call void @llvm.dbg.value(metadata i1 %1, metadata !30, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !33
  call void @llvm.dbg.value(metadata i1 %2, metadata !31, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !33
  call void @llvm.dbg.value(metadata i1 %3, metadata !32, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !33
  call void @llvm.dbg.value(metadata i1 %0, metadata !35, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !41
  call void @llvm.dbg.value(metadata i1 %1, metadata !38, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !41
  call void @llvm.dbg.value(metadata i1 %2, metadata !39, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !41
  call void @llvm.dbg.value(metadata i1 %3, metadata !40, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !41
  ret i1 true, !dbg !43
}
 ```
 
 gcc gets it right.
 
 Assembly code for the problematic case:
 ```
 check4(bool, bool, bool, bool):                          # @check4(bool, bool, bool, bool)
        or      edx, ecx
        mov     eax, edx
        or      eax, esi
        and     eax, edi
        test    esi, esi
        cmovne  edx, edi
        and     edx, edi
        xor     eax, edx
        xor     al, 1
        ret
 ```
 All instructions apart from the final three seem superfluous.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJztWVtvozgU_jXkxWoUDOTykIe2mZEqzaij1WpX2pfI2IfEU4Ij26SZ_fV7bMiFS1ajtg9RVGSB8blwPuxzwhenSvyaPxXEroFwJYCkkKvXgD76kawsuJWqIMF4xNfAX2LsELNWZS6IBltqL7K6BLwMg9EiGN0_WSIUGFIo10E_0pDXNRSkNLJYOf2Ajl1znUeSlpbI2qSrdvRan3G0av7WWGYlJ6lSObHsBeJdGNCpv2Xet-ulxx4_9kRAZySYPFRuCB4HNHTKSBWfM3RKj9ga4_zCuHMaRLXPYLI4D7wbKX1npMfHOj-HcPihU8eCwq_YyPPWyo00-IpTsBY0kZkzJzg1pQFBZGEsMDHsjb2KqJr-98V8mqPKgTt5s8oiWmA7ez09Sj3vt7kkqvO3b399J09_kBUUoJn1CP2K3mqV5rDxk8GZAff27owV-GB8xgO2cELuniP_qP5FJyCTBRBh1DJXnOW40MsCB8m_oBXscTWHJIhHy3_G1TtL8cCn4GhbMaCJT4F-UXhZRC-LXOTEx7Usi4JtQCyZEBpF0QhPoUhX7hJOzycItXOyU1K4wPN8txmi2nDHcsxrOt2AZYJZ5oHVIR_H0Bel7ZHF05f9VoMxWDvQweLv5fOPpZuTJVfFDrR1Bh4fiu7__IKhGrkqQNRDPdrT_9XG9OIvyzrgmW-PZ2gxUd6CNOwgjW4UaWcGaXyjSDszSJMbRdrN08m1I42ij8nTqIP9RpB28jTqYL8RpJ08ja7-V-aEFONP3OcMUfp84jysk8q4qZLUKmHLa3JmMvEmrBC1zbi2GV2yeV_FiMbX_s5j-kEVY3ajSDtZE199bXwj0k7FiK--Np6QYvxTn9v7Yz3w8-SpddMmPrOZNUvItL-ENEzCkbcxkAO3td2s5hNnhORUkPq9hK1ow7oEJZOW1Xn5CmnbKrwA8miFzPGgS1s64xYTJC2iRurLgQzKw98cWjvoB_pnkCSRLGcrc0762s4-Wd8n67s1pJ-s7_aQfrK-20P6yfpuD2mXa119RcLv6Y_J0-mNIu3m6fWzyrch7XKtq6-9J6Q1pehhHdFvMooV52QF1riNSy1Xaztsyu-NgU2a_6q2VDOkO317Txe5RnOzzcXYf3VshVw88NvfTeVv-zpu1rkDQ_YHiL3TAb5vyjdqV8lZJRf7C_a13Mim3P2F1bBvyS0Y6-Vo2GfPMQCkY8f42vZH_xfk-zrAS_Ef5CyvlmlDiAvowsTdYw65vVRd-n1zQ9iWaUsyrTbVhroskDratQZABg4bYsot6CwvVWmGAzGPxCyasYGVNof5UwFZJrmEwlYLqbGbaeRmm4OfPWAFgWOyDUqdz9fWbo1bYH7_dyXtukyHXG3wxuV2fbnDJfkTuTDeSmNKQAb8NYmjMBqs52EM6Xg8jqbxJMlCkURMJIzTdAIZZTThg5ylkJt5kDwElBbwSrwL7AfJYiDndETpKBrN3JcsTYZRxKeTWcQFiHGSxFNcmZgKMh_6UqP0aqDnPqS0RCKOFUgaa05CZny6g38c-melXSs9_4lU13Cl8CXepWgy8DHMPYb_ADMZyFs">