llvm / llvm/llvm-project

x86 optimizing load of constants like 0x300000000 (== (3<<32))

Open
#172,281 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

backend:X86 missed-optimization
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

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.)

```c
#include
#include
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);
}
```

[Compiler Explorer link](https://godbolt.org/z/3PW1G3Mox)

Note: The test code is adapted from [a related issue report I reported to GCC](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122904). (GCC missed a different optimization with a constant like 0x300000000.)

x86-64 clang 21.1.0 with `-Os` option:

```assembly
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.)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Compiler Explorer example and the x86-64 clang -Os output shown in the issue, comparing the constant-load sequences with the manually shifted versions. Trace the relevant LLVM x86-64 constant materialization and optimization tests, then verify that the requested size optimization appears for the demonstrated cases without regressing other modes.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
compilers
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.