[fpc-devel] Attn: J. Gareth // 3.3.1 opt = slower // Fwd: [Lazarus] Faster than popcnt
Martin Frb
lazarus at mfriebe.de
Tue Jan 4 16:31:42 CET 2022
On 04/01/2022 10:31, Marco van de Voort via fpc-devel wrote:
>
>
> Weird as mine is inlined with -Cpcoreavx -O4, with no special handling
> for 0. But that does put some things on shaky ground. Maybe zero the
> result before hand?
Same here.
----------------------------------------
About UTF8LengthFast()
Well, before I get to this, I noted something weird.....
2 runs, compiled with the same compiler ( 3.2.3 ), and the same
settings, with the only difference: -gw3 or not -gw3
=> And the speed differed. 600 (with dwarf) vs 700 (no dwarf) /
reproducible.
So then
=> I compiled the app, with the same 3.2.3 (and I compiled WITHOUT -a
/ though with -al I get the same results)
=> I compiled once with -gw3 , and once without dwarf info
=> I used objdump to dis-assemble the exe.
=> I diffed (and searched for 0x101010.... (only used in the ...Fast code)
--> _*The assembler is identical.*_
Yet one is faster. (the one WITH dwarf)
The calling code in the main body is the same too (as far as I could
see), except that the address of the callee is different (but it is just
20 calls per measurement)
I did those runs OUTSIDE the IDE.
So no debugger in the background.
Win64 / 64 bit
Core I7 8600K
Using 3.3.1 the speed is equal. Never mind if dwarf is generated or not.
(I did not compare the asm for that...)
---------------------
Clinging to straws, there is one (maybe) diff in the 3.2.3 with/without
dwarf assembler.
*** I am totally out of my depth here ****
Alignment. 16 vs 32 bit. Can that make a difference?
According to:
https://stackoverflow.com/questions/61016077/32-byte-aligned-routine-does-not-fit-the-uops-cache
> The Decoded ICache consists of 32 sets. Each set contains eight
> Ways. Each Way can hold up to six micro-ops.
>
> All micro-ops in a Way represent instructions which are statically
> contiguous in the code and have their EIPs within _*the same aligned
> 32-byte region*_.
So the alignment of the 2 procedures differs by 16 bytes
The proc entry is at
With dwarf 100001870
without 100001860 // actually this is 32byte aligned (but slower)
Yet, maybe it matters which statements in the big loop happen to fall
into the same 32byte block???
The loop starting with
for i := 1 to (ByteCount-cnt) div sizeof(PtrInt) do
With DWARF (faster):
1000018f0: 49 83 c2 01 add $0x1,%r10
1000018f4: 4c 8b 19 mov (%rcx),%r11
1000018f7: 4d 89 d8 mov %r11,%r8
1000018fa: 48 bf 80 80 80 80 80 movabs $0x8080808080808080,%rdi
100001901: 80 80 80
100001904: 49 21 f8 and %rdi,%r8
100001907: 49 c1 e8 07 shr $0x7,%r8
10000190b: 49 f7 d3 not %r11
10000190e: 49 c1 eb 06 shr $0x6,%r11
100001912: 4d 21 d8 and %r11,%r8
100001915: 4c 89 c3 mov %r8,%rbx
100001918: 49 bb 01 01 01 01 01 movabs $0x101010101010101,%r11
10000191f: 01 01 01
100001922: 4d 0f af c3 imul %r11,%r8
100001926: 49 c1 e8 38 shr $0x38,%r8
10000192a: 4c 01 c6 add %r8,%rsi
10000192d: 48 83 c1 08 add $0x8,%rcx
100001931: 4d 39 d1 cmp %r10,%r9
100001934: 7f ba jg 1000018f0
<P$PROGRAM_$$_UTF8LENGTHFAST$PCHAR$INT64$$INT64+0x80>
WITHOUT:
1000018e0: 49 83 c2 01 add $0x1,%r10
1000018e4: 4c 8b 19 mov (%rcx),%r11
1000018e7: 4d 89 d8 mov %r11,%r8
1000018ea: 48 bf 80 80 80 80 80 movabs $0x8080808080808080,%rdi
1000018f1: 80 80 80
1000018f4: 49 21 f8 and %rdi,%r8
1000018f7: 49 c1 e8 07 shr $0x7,%r8
1000018fb: 49 f7 d3 not %r11
1000018fe: 49 c1 eb 06 shr $0x6,%r11
100001902: 4d 21 d8 and %r11,%r8
100001905: 4c 89 c3 mov %r8,%rbx
100001908: 49 bb 01 01 01 01 01 movabs $0x101010101010101,%r11
10000190f: 01 01 01
100001912: 4d 0f af c3 imul %r11,%r8
100001916: 49 c1 e8 38 shr $0x38,%r8
10000191a: 4c 01 c6 add %r8,%rsi
10000191d: 48 83 c1 08 add $0x8,%rcx
100001921: 4d 39 d1 cmp %r10,%r9
100001924: 7f ba jg 0x1000018e0
----------------------------------------
*** written before I got into the above......
-------
About UTF8LengthFast()
I notice 3 differences.
Though I only compare the O4 result, and have no idea what is
pre-peephole and post-peephole.
1) As you say: different registers (but the same statements, in the same
order).
No idea if that affects the CPU.
2) One extra statement in 3.3.1
movq %r10,%r8 //// <<<<<<<<<<<<<<< not in 3.2.3
movq $72340172838076673,%r10
imulq %r10,%r8
3) I do have "dwarf" enabled. Even though, at O4 that is not expected to
do any good.
I noted that in 3.3.1 this leads to way more asm-labels than in 3.2.3.
Those labels are only referred to by dwarf-line info (some asm
statements, are reported to be in the "begin" line. Even so, they are
clearly not.
- It could be a result of the peephole opt.
- But it could also be that the peephole is affected by the presence of
those labels.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20220104/f5632833/attachment.htm>
More information about the fpc-devel
mailing list