-
Notifications
You must be signed in to change notification settings - Fork 15.5k
Open
Description
For x86-64, the load of a 64-bit constant with lower bits being zero can be optimized as a 32-bit load followed by a left shift. This can result in code that's one byte smaller.
GCC performs this optimization in -Os and -Oz modes. Clang doesn't yet. Thus this feature request. (I specifically request this in -Oz mode. Whether it would perform also in -Os mode is left for the compiler developers to decide.)
#include <stdint.h>
#include <stdbool.h>
void func1a(void) {
uint64_t x = 0x300000000; // GCC can optimize this to (3UL << 32)
__asm__("" :: "r"(x));
}
void func1c(void) {
uint64_t x = 3UL;
__asm__("" : "+r"(x));
x <<= 32;
__asm__("" :: "r"(x));
}
bool func3(uint64_t x) {
return x <= 0x300000000; // GCC can optimize this to (x <= (3UL << 32))
}
bool func4(uint64_t x) {
return x > 0x300000000; // GCC can optimize this to (x > (3UL << 32))
}
bool func3b(uint64_t x) {
uint64_t y = 3UL;
__asm__("" : "+r"(y));
return x <= (y << 32);
}Note: The test code is adapted from a related issue report I reported to GCC. (GCC missed a different optimization with a constant like 0x300000000.)
x86-64 clang 21.1.0 with -Os option:
func1a: # 11 bytes
movabsq $12884901888, %rax
retq
func1c: # 10 bytes
movl $3, %eax
shlq $32, %rax
retq
func3: # 17 bytes
movabsq $12884901889, %rax
cmpq %rax, %rdi
setb %al
retq
func3b: # 16 bytes
movl $3, %eax
shlq $32, %rax
cmpq %rax, %rdi
setbe %al
retq(The constant that applies to my use case is 0x7ff0000000000000, the bit mask that can be used to check floating point infinities and NaNs.)