3 ms·
ARM64 has many registers but I believe the lack of suitably large immediate values and, apparently, compilers that are willing to use them all across functions,
by userbinator 1y ago
ARM64 has many registers but I believe the lack of suitably large immediate values and, apparently, compilers that are willing to use them all across functions, puts it at a disadvantage here. Assuming we want the return value in eax and the leading count comes in cl, this can be done branchlessly and data-lessly on x86 as follows:
mov eax, 0x00043201
test cl, 8
setz al
shl cl, 2
shr eax, cl
and eax, 15
Something similar may be possible on ARM64, but I suspect it will definitely be more than 19 bytes ;-)
- shiftingleft 1y agoShouldn't your snippet be using lzcnt? I can't see how this would result in the desired lookup. for Zen5 rustc creates the following: utf8_sequence_length_lookup: shl edi, 24 mov ecx, 274945 not edi lzcnt eax, edi shl al, 2 shrx rax, rcx, rax and al, 7 ret https://rust.godbolt.org/z/hz1eKjnaG https://rust.godbolt.org/z/hz1eKjnaG
- Cold_Miserable 1y agoI can't see any elegant solution. \n Struggling proc \n lzcnt ecx,ecx \n test cl,cl \n setz al \n lea edx,[ecx-2] ;[0,1,2] \n cmp rdx,2 \n cmovle eax,ecx \n ret \n Struggling endp
- userbinator 1y agoand the leading count comes in cl We can assume the count has already been done.
- shiftingleft 1y agoAh I can't read, thanks :-)
- deleted 1y ago[deleted]
- hairtuq 1y agoThe mapping after we have the leading 1's count can be done in 3 instructions (in 32-bit math) on either x86 or ARM: t = 0x2020c6 >> x return (t << (t & 31)) >> 27
- deleted 1y ago[deleted]
- userbinator 1y agoThat is extremely clever (how did you come up with it?), but definitely needs more than 3 instructions (you need at least 2 just to shift the constant): mov eax, 0x2020c6 shr eax, cl mov cl, al shl eax, cl shr eax, 27 Yet those 14 bytes definitely beats my first attempt... although I've since found an even shorter solution: mov ax, 0x4681 lea ecx, [ecx+ecx*2] shr eax, cl and eax, 7 12 bytes.
- Cold_Miserable 1y agoI see what you're doing. 13 bytes, 3 cycles. Why does newline not work? lzcnt ecx,ecx mov eax, 00100 0011 0010 0000 0001b shl ecx,2 shrx eax,eax,ecx and eax,15
- teo_zero 1y agoClever, but I prefer the parent's proposal: return (0x43201 >> x*4) & 7 It's more understandable and the number of instructions is the same.