Missed load widening around atomic load
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
The optimizer generally understands that it can widen 4 adjacent 1-byte loads into a 4 byte load, even if there is another load between them in the original source.
However, it does not do so when the in-between load is atomic, even if the load is using relaxed memory ordering, and as such the compiler is allowed to reorder the loads around it.
[*Example on godbolt*](https://godbolt.org/z/jzP86PTaG)
```cpp
#include
#include
uint8_t arr[4];
std::atomic atomic_b;
bool b;
uint32_t wide_load1() {
uint32_t ret = 0;
ret |= arr[3] << 24;
bool local = atomic_b.load(std::memory_order_relaxed);
ret |= arr[2] << 16;
ret |= arr[1] << 8;
ret |= arr[0] << 0;
if (local) {
return ret;
}
return -ret;
}
uint32_t wide_load3() {
uint32_t ret = 0;
ret |= arr[3] << 24;
bool local = b;
ret |= arr[2] << 16;
ret |= arr[1] << 8;
ret |= arr[0] << 0;
if (local) {
return ret;
}
return -ret;
}
```
As relaxed atomic allows reordering around it, `wide_load1` should read from `arr` with single 4 byte load.
---
AIUI, this should also be an allowed optimization if the load is done with `acquire` memory order.
Contributor guide
Research direction
Reproduce the Godbolt example and compare generated code for wide_load1 and wide_load3, then trace LLVM's load-widening optimization handling of an intervening relaxed atomic load. No source file or test is named in the issue; done means the relaxed case, and potentially the acquire case, widens to one 4-byte load while preserving atomic semantics, with regression coverage.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100