0

I tried compiling the following code on Compiler Explorer:

int index(int *arr, unsigned int i) {
    return arr[i];
}

With x86-64 gcc 11.2, on -O2 the following code is generated:

index(int*, unsigned int):
    mov     esi, esi
    mov     eax, DWORD PTR [rdi+rsi*4]
    ret

I've seen this answer, which says that moving a register to itself is an 'inefficient NOP' and was deemed to be 'an artifact of code-generation from a non-optimizing compiler'.

Why does GCC generate mov esi, esi here on -O2?

https://godbolt.org/z/bE4xhc8Tx

konsolas
  • 1,041
  • 11
  • 24
  • [MSVC compiler generates mov ecx, ecx that looks useless](https://stackoverflow.com/q/59482079/995714) – phuclv Aug 23 '21 at 11:58
  • 2
    There's a big difference. `mov rsi, rsi` would be a no-op. But `mov esi, esi` in 64-bit mode isn't a no-op. It zeroes the high half of rsi, effectively zero-extending a 32-bit `unsigned int` into an unsigned 64-bit quantity that can be safely added to a 64-bit pointer. – Nate Eldredge Aug 23 '21 at 13:41
  • That's a missed optimization; gcc should pick one of the other call-clobbered registers so [mov-elimination](https://stackoverflow.com/questions/44169342/can-x86s-mov-really-be-free-why-cant-i-reproduce-this-at-all) can work for this zero extension, e.g. `mov eax, esi`. / `mov eax, [rdi+rax*4]` – Peter Cordes Aug 23 '21 at 13:56

0 Answers0