https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99470
Bug ID: 99470
Summary: Convert fixed index addition to array address offset
Product: gcc
Version: 11.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: redbeard0531 at gmail dot com
Target Milestone: ---
These two functions do the same thing but f() is the cleaner source code
(especially when arr is a std::array) while g() generates better code:
https://gcc.godbolt.org/z/vTT399
#include <cstdint>
inline int8_t arr[256];
bool f(int a, int b) {
return arr[a+128] == arr[b+128];
}
bool g(int a, int b) {
return (arr+128)[a] == (arr+128)[b];
}
f(int, int):
sub edi, -128
sub esi, -128
lea rax, arr[rip]
movsx rdi, edi
movsx rsi, esi
movzx edx, BYTE PTR [rax+rsi]
cmp BYTE PTR [rax+rdi], dl
sete al
ret
g(int, int):
lea rax, arr[rip+128]
movsx rdi, edi
movsx rsi, esi
movzx edx, BYTE PTR [rax+rsi]
cmp BYTE PTR [rax+rdi], dl
sete al
ret
In addition to only doing the +128 once, it also ends up being completely free
in g() because the assembler (or linker?) folds the addition into the address
calculation by adjusting the offset of the rip-relative address. In the godbolt
link, you can see that when compiled to binary, the LEA instruction uses the
same form in both f() and g(), so the addition really is free in g().