Avoid materialising `-k` by rewriting `use(a + k, b + (-k))` to `use(a + k, b - k)`
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
LLVM rewrites expressions of the form `a - k` to `a + (-k)` when `k` is a constant. This is usually beneficial because it may expose more associativity/commutativity. But, if `k` is a constant that has to be materialized by the target because it doesn't fit in an immediate, the rewrite should be undone, so that only `k` has to be materialised:
# C++ examples
https://godbolt.org/z/G4P76sfPT
```c++
using u32 = unsigned int;
using f32 = float;
using f64 = double;
u32 use(u32 a, u32 b);
f32 use(f32 a, f32 b);
f64 use(f64 a, f64 b);
auto src(u32 a, u32 b) {
u32 k = (1 << 12) + 1;
return use(a + k, b - k);
}
auto src(f32 a, f32 b) {
f32 k = 1.0;
return use(a + k, b - k);
}
auto src(f64 a, f64 b) {
f64 k = 1.0;
return use(a + k, b - k);
}
```
# Current AArch64 assembly
```asm
src(unsigned int, unsigned int):
mov w8, #4097
mov w9, #-4097
add w0, w0, w8
add w1, w1, w9
b use(unsigned int, unsigned int)
src(float, float):
fmov s2, #1.00000000
fmov s3, #-1.00000000
fadd s0, s0, s2
fadd s1, s1, s3
b use(float, float)
src(double, double):
fmov d2, #1.00000000
fmov d3, #-1.00000000
fadd d0, d0, d2
fadd d1, d1, d3
b use(double, double)
```
# Expected AArch64 assembly
```asm
src(unsigned int, unsigned int):
mov w8, #4097
add w0, w0, w8
sub w1, w1, w9
b use(unsigned int, unsigned int)
src(float, float):
fmov s2, #1.00000000
fadd s0, s0, s2
fsub s1, s1, s2
b use(float, float)
src(double, double):
fmov d2, #1.00000000
fadd d0, d0, d2
fsub d1, d1, d2
b use(double, double)
```
# Current x86_64 assembly
```asm
src(unsigned int, unsigned int):
add edi, 4097
add esi, -4097
jmp use(unsigned int, unsigned int)@PLT
.LCPI1_0:
.long 0x3f800000
.LCPI1_1:
.long 0xbf800000
src(float, float):
addss xmm0, dword ptr [rip + .LCPI1_0]
addss xmm1, dword ptr [rip + .LCPI1_1]
jmp use(float, float)@PLT
.LCPI2_0:
.quad 0x3ff0000000000000
.LCPI2_1:
.quad 0xbff0000000000000
src(double, double):
addsd xmm0, qword ptr [rip + .LCPI2_0]
addsd xmm1, qword ptr [rip + .LCPI2_1]
jmp use(double, double)@PLT
```
# Expected x86_64 assembly
```asm
src(unsigned int, unsigned int):
add edi, 4097
add esi, -4097
jmp use(unsigned int, unsigned int)@PLT
.LCPI1_0:
.long 0x3f800000
src(float, float):
addss xmm0, dword ptr [rip + .LCPI1_0]
subss xmm1, dword ptr [rip + .LCPI1_0]
jmp use(float, float)@PLT
.LCPI2_0:
.quad 0x3ff0000000000000
src(double, double):
addsd xmm0, qword ptr [rip + .LCPI2_0]
subsd xmm1, qword ptr [rip + .LCPI2_0]
jmp use(double, double)@PLT
```
Contributor guide
Assessment
This issue has not been assessed yet.