<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/66574>66574</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
`if`-chain vs `switch` code generation
</td>
</tr>
<tr>
<th>Labels</th>
<td>
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
firewave
</td>
</tr>
</table>
<pre>
All these code samples do the same and I would have expected them to generate essentially the same code but they are all different:
```cpp
int f0(const char c)
{
if (c == ' ' || c == '\0')
return 2;
if (c == '|')
return 1;
return 0;
}
```
```asm
f0(char): # @f0(char)
xor ecx, ecx
cmp dil, 124
sete cl
test dil, -33
mov eax, 2
cmovne eax, ecx
ret
```
The best code according to `llvm-mca`.
```cpp
int f1(const char c)
{
switch (c) {
case ' ':
case '\0':
return 2;
case '|':
return 1;
}
return 0;
}
```
```asm
f1(char): # @f1(char)
mov eax, 2
test edi, edi
je .LBB1_5
cmp edi, 32
je .LBB1_5
cmp edi, 124
jne .LBB1_4
mov eax, 1
ret
.LBB1_4:
xor eax, eax
.LBB1_5:
ret
```
Adds compares and branches.
```cpp
int f1a(const char c)
{
switch (c) {
case '|':
return 1;
case ' ':
case '\0':
return 2;
}
return 0;
}
```
```asm
f1a(char): # @f1a(char)
test edi, edi
je .LBB2_4
cmp edi, 124
je .LBB2_2
cmp edi, 32
jne .LBB2_5
.LBB2_4:
mov eax, 2
ret
.LBB2_2:
mov eax, 1
ret
.LBB2_5:
xor eax, eax
ret
```
Leads to different code than `f1()` since the order of the cases matters. I always thought that's why you should prefer a `switch` over an `if`-chain.
```cpp
int f2(const char c)
{
switch (c) {
case ' ':
case '\0':
return 2;
}
if (c == '|')
return 1;
return 0;
}
```
```asm
f2(char): # @f2(char)
mov eax, 2
test edi, -33
jne .LBB3_1
ret
.LBB3_1:
xor eax, eax
cmp dil, 124
sete al
ret
```
Not the same as `f0()` but better as `f1()`. I would not have expected that splitting up a `switch` leads to more efficient code.
GCC produces generally worse code but appears to be more consistent
https://godbolt.org/z/E7rso66n3
There's even more fun if such code is part of a bigger function. That's how I arrived at this. I had to extract that into a separate function and in some case change the code used in `f0()` to the one used in `f2()` to get better generated code. I have not yet been able to reduce those other cases yet but they are not in the scope of this ticket anyways.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzMl01v2zgTxz8NfRnEkChbcg4-NMnjBwWKPfVejKiRxa5ECiRlx_vpF6RebDlv3iLFrpBEMYdD0uTvP5xBa-VeEW3Z-oGtnxbYuUqbbSkNHfFAi1wXp-2XugZXkSUQuiCw2LQ1WSi0b_UfCVAV8BWOuqsLqPBAQM8tCUeF79KA07AnRQYdAVlLykms69PZPwycd863nAANAdY1FLIsyZByLPnCoicWjX_TqP8Rbdu3SOWgjBjfCK2sA1GhAcH4_dA_e-j_AQCQJfh-wJInljwB41n_mz2y7BEu29n6MfKvcRgYHkOuMwo4S94d1o_4tnfMkgc4W4bWaBqTZU9XX_bVHUDb9C39t6_Q-AmTabY3H8YTYKto5jZb57M24U3imfHH8JrZRdOGdyFrb4_5arBbchQ61HMHR9ZdONwlydze6EM_IYYJ-WAVjT4omppfrMOQe2ejvlcEuZ84EIZCaFNItfdEsjSq60Nz1whkabS8AbD4JsDsUTpRBRoYv4eZLewLWhqxm8C-No7sXdtf52_y6pF7xymeQTtB9jkIxr-GYPwWgm8QccUTFTKAUci5_SfB8tvDQ_xj_Tq4g1_CX7iFZ-575XSmffRSdOG1evd7xIN1Ind0uj63SYID-vh82X997v--Br4UhQWhmxYN2RCqc4NKVGRvgh4_lfrbEJ0Q-d3K-Q0iwLkKJsrxLcxvBJlfY_Uhkxck8x_8dZJf4H8BMh_xH6e_3lMP9uvinLHtJ3_N9SNN8EvGP9DEBxr4RlhYH_WnnKK_EVyFyt8EIQj5k0kjsFIJCrmJNgUZ0GX44AGz0KBzZOwSvgLWRzxZcJXu9pVPXdAxnlk4Vic46Q5sFfKh1lBJBtBP06vET6IPvi3MLUuWRneiQqluEST_r95CMyH96_kQ_7XLiH_KZXRObi71lPyI31GJt95M-5vZ1_CMSRjW_yRb-kO7i5zeBmFEZ2H4BD0nz_9oPKtmOeX_SrsXNQA6sG0tnfO5V9dei6Ee1dloQ0BlKYUcJTqTxP8fH6E1uugE2aGk8HXEURt7UURg2xKaMGBO_ZheMNI6X0tcDFc511q_6XzH-G6vi1zXbqnNnvHdX4zv_pcZq9NUJVcppaEgdDqQ6ocvO-WJt52o-mVICy0a52MHQi73ezK-k3BSqyV8H0NFpY8-kBgjD1QA-t2XIbZUWPjl07MzKPrYAlI5DQiWWgyV1DheuNKlAqubPkr5wKD2fQgLq-kshR5X5-n6Ck6reQ8-67Gn6dDHGq7oDyYs80DhwE-hFynAvCbvZsgfkg-OlkC7iswQQEPPy0rPu0vVcyd0S328lRacFH-SA1QnH2eXi2KbFPfJPS5oG6f3q026WcXxotqu0iIiWos1iSzFMlqna7FZpSVuMrHBeLOQWx7xJLqP05iv0nW8zLI0wzKPcp6KeLNJ2CqiBmW99AWBP_-FtLajbZqus9WixpxqO5bIZhuqhrzbW7aKammdPbs56WrazmM6HOyc9nAkw15KrRadqbdXJEpXdflS6IbxnR98eN21Rv8k4RjfhQVaxndhjX8HAAD__w36KeI">