llvm / llvm/llvm-project

[Missed Optimization] Idiom recognition for C23 `memalignment` pointer alignment loops

Open
#216,390 0 comments 1 reaction 0 assignees View on GitHub
loopoptim missed-optimization
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

### Description
LLVM misses an idiom recognition opportunity to optimize a pointer-alignment loop into a simple bitwise AND operation.

With C23 introducing the `memalignment` function, it is now possible to write strictly standard-conforming pointer alignment functions without relying on implementation-defined pointer-to-integer casts or toolchain-specific extensions. The loop iteratively adds or subtracts the pointer's current alignment from itself, effectively clearing the lowest set bit until the target power-of-two alignment is met.

Unfortunately, LLVM fails to recognize this loop idiom and emits a literal loop instead of a mathematical shortcut.

### Reproducer
A minimal reproducible example can be found on Compiler Explorer: https://godbolt.org/z/EPbs8v35c
A more extensive example suite containing up-alignment and `std::align` equivalents as well as alternative implementation approaches is available here: https://godbolt.org/z/qv1MMs6eT

```c
void *align_down(void *ptr, size_t alignment) {
if (!stdc_has_single_bit(alignment)) {
unreachable();
}
while (memalignment(ptr) < alignment) {
ptr = (unsigned char *)ptr - memalignment(ptr);
}
return ptr;
}
```

### Observed Assembler (Clang -Os)
The loop survives scalar optimization passes intact:

```asm
align_down:
mov rax, rdi
mov rcx, rdi
neg rcx
and rcx, rdi
.LBB0_2:
cmp rcx, rsi
jae .LBB0_3
sub rax, rcx
mov rcx, rax
neg rcx
and rcx, rax
jmp .LBB0_2
.LBB0_3:
ret
```

### Expected Output
The loop should be lowered to a simple bitmask, matching the code generated by `__builtin_align_down`:

```asm
align_down:
mov rax, rsi
neg rax
and rax, rdi
ret
```

### Additional Context
- This behavior is consistent across all Clang versions and target architectures available on compiler explorer.
- Compiler explorer does not yet expose `memalignment` to its Clang targets, so the examples use a manually written fallback implementation. I have verified locally that using a native C23 standard library implementation of `memalignment` yields the exact same loop output as using the fallback.
- Since this pattern represents the only strictly standard-compliant way to dynamically align pointers in modern C, optimizing this idiom would significantly benefit safety-conscious, standard-conforming codebases.

Contributor guide

Open the contributing guide

Research direction

Start with the Clang reproducer on Compiler Explorer and compare the loop output with the __builtin_align_down output. Read the scalar optimization passes involved in the loop and pointer-alignment handling, then verify that the C23 memalignment form is lowered to the expected bitmask without changing other alignment cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
compilers, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.