GCC 4.4.3 erzeugte die folgende x86_64-Assembly. Der Teil, der mich verwirrt, ist die mov %eax,%eax
. Verschieben Sie das Register zu sich selbst? Warum?Warum hat GCC mov% eax,% eax generiert und was bedeutet das?
23b6c: 31 c9 xor %ecx,%ecx ; the 0 value for shift
23b6e: 80 7f 60 00 cmpb $0x0,0x60(%rdi) ; is it shifted?
23b72: 74 03 je 23b77
23b74: 8b 4f 64 mov 0x64(%rdi),%ecx ; is shifted so load shift value to ecx
23b77: 48 8b 57 38 mov 0x38(%rdi),%rdx ; map base
23b7b: 48 03 57 58 add 0x58(%rdi),%rdx ; plus offset to value
23b7f: 8b 02 mov (%rdx),%eax ; load map_used value to eax
23b81: 89 c0 mov %eax,%eax ; then what the heck is this? promotion from uint32 to 64-bit size_t?
23b83: 48 d3 e0 shl %cl,%rax ; shift rax/eax by cl/ecx
23b86: c3 retq
Der C++ Code für diese Funktion ist:
uint32_t shift = used_is_shifted ? shift_ : 0;
le_uint32_t le_map_used = *used_p();
size_t map_used = le_map_used;
return map_used << shift;
Ein le_uint32_t
eine Klasse ist, die auf Big-Endian-Maschinen-Byte-Swap-Operationen wickelt. Auf x86 tut es nichts. Die used_p()
-Funktion berechnet einen Zeiger aus der Kartenbasis + Offset und gibt einen Zeiger des richtigen Typs zurück.
Siehe http://stackoverflow.com/questions/2703394/whats-the-point-of-lea-eax-ax – nos
@nos: Möglicherweise. Aber warum sollte der GCC dort einen Nop suchen? Es gibt nichts auszurichten. –
Selbst wenn es etwas zu justieren gab (ein Sprung irgendwo, den wir nicht sehen müssen, um auf den nächsten Befehl zu landen), ist es nicht - die Adresse des SHL-Befehls ist nur auf ein Byte ausgerichtet. Dies sieht einfach wie ein Optimierungsfehler aus. Probieren Sie verschiedene Flags und neuere Versionen von gcc (4.4.3 wird ziemlich alt) und sehen Sie, welchen Effekt es hat. –