GCC 4.4.3 wygenerował następujący zestaw x86_64. Częścią, która mnie myli, jest mov %eax,%eax
. Przenieść rejestr do siebie? Czemu?Dlaczego GCC generuje mov% eax,% eax i co to znaczy?
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
C++ kod dla tej funkcji jest następująca:
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;
le_uint32_t
to klasa, która owija operacji bajt-swap na maszynach big-endian. Na x86 nic nie robi. Funkcja used_p()
oblicza wskaźnik z podstawy mapy + przesunięcie i zwraca wskaźnik odpowiedniego typu.
Zobacz http://stackoverflow.com/questions/2703394/whats-the-point-of-lea-eax-eax – nos
@nos: Możliwe. Ale z jakiego powodu GCC chciałby mieć tam nop? Nie ma nic do wyrównania. –
Nawet jeśli było coś do wyrównania (skoku gdzieś nie widzimy potrzeby wylądowania na następnej instrukcji), to nie jest - adres instrukcji SHL jest wyrównany tylko do bajtu. To po prostu wygląda jak błąd optymalizatora. Wypróbuj różne flagi i nowsze wersje gcc (4.4.3 jest coraz bardziej nieaktualna) i zobacz, jaki ma efekt. –