Consider this (https://godbolt.org/z/qqs1doPTT):
static bool IsLWS(byte ch)
{
return (ch <= 32) && (ch == 32 || ch == 10 || ch == 13 || ch == 9);
}
which Roslyn turns into:
static bool IsLWS1(byte ch)
{
if (ch <= 32)
{
if (ch != 32 && ch != 10 && ch != 13)
{
return ch == 9;
}
return true;
}
return false;
}
Codegen is:
G_M000_IG02: ;; offset=0x0000
movzx rcx, cl
cmp ecx, 32
jle SHORT G_M000_IG05
G_M000_IG03: ;; offset=0x0008
xor eax, eax
G_M000_IG04: ;; offset=0x000A
ret
G_M000_IG05: ;; offset=0x000B
cmp ecx, 32
ja SHORT G_M000_IG09
G_M000_IG06: ;; offset=0x0010
mov eax, 0xFFFFDBFF
bt rax, rcx
jb SHORT G_M000_IG09
G_M000_IG07: ;; offset=0x001B
mov eax, 1
G_M000_IG08: ;; offset=0x0020
ret
G_M000_IG09: ;; offset=0x0021
cmp ecx, 9
sete al
movzx rax, al
G_M000_IG10: ;; offset=0x002A
ret
There are several things to improve here, but the most important is that the compare against 9 (in G_M000_IG09) is not made part of the switch - it should be part of the bittest.
The issue is that the JTRUE for the ch == 9 jumps to a different RETURN 1 block than the other JTRUEs. Tail merging only merges the RETURN 0 blocks for some reason:
*************** Starting PHASE Post-morph head and tail merge
A set of 2 return blocks end with the same tree
STMT00008 ( 0x014[E--] ... ??? )
[000034] ----------- * RETURN int
[000033] ----------- \--* CNS_INT int 0
Will cross-jump to BB09
unlinking STMT00001 ( 0x01C[E--] ... 0x01D )
[000005] -----+----- * RETURN int
[000025] -----+----- \--* CNS_INT int 0
from BB07
BB07 becomes empty
setting likelihood of BB07 -> BB09 to 1
*************** Finishing PHASE Post-morph head and tail merge
So to fix this either tail merging should be made more aggressive (and also merge the RETURN 1) or switch recognition needs to deal with it.
Btw MSVC has the same issue.
Consider this (https://godbolt.org/z/qqs1doPTT):
which Roslyn turns into:
Codegen is:
There are several things to improve here, but the most important is that the compare against 9 (in
G_M000_IG09) is not made part of the switch - it should be part of the bittest.The issue is that the JTRUE for the
ch == 9jumps to a different RETURN 1 block than the other JTRUEs. Tail merging only merges the RETURN 0 blocks for some reason:So to fix this either tail merging should be made more aggressive (and also merge the RETURN 1) or switch recognition needs to deal with it.
Btw MSVC has the same issue.