-
Notifications
You must be signed in to change notification settings - Fork 14.7k
Closed
Description
The ORR
, AND
and EOR
instructions only accept immediates in a specific form. For immediates that do not fit in this form, we have to materialise it with MOV+MOVK
. However, sometimes instead of materialising, we could decompose the immediate into two immediates that are accepted.
C++ example: https://godbolt.org/z/vzzaTzseE
(The volatile
keyword is required to prevent LLVM performing constant folding)
alive proof: https://alive2.llvm.org/ce/z/NmrTqz
#include <cstdint>
typedef uint32_t u32;
u32 src1(u32 x) { return x | 0xF0'00'00'F0; }
u32 tgt1(volatile u32 x) {
x |= 0xF0'00'00'0;
x |= 0x00'00'00'F0;
return x;
}
u32 src2(u32 x) { return x & 0xF0'00'00'F0; }
u32 tgt2(volatile u32 x) {
x &= 0xF0'00'00'FF;
x &= 0xFF'FF'FF'F0;
return x;
}
u32 src3(u32 x) { return x ^ 0xF0'00'00'F0; }
u32 tgt3(volatile u32 x) {
x ^= 0xF0'00'00'00;
x ^= 0x00'00'00'F0;
return x;
}
src1(unsigned int):
mov w8, #240
movk w8, #61440, lsl #16
orr w0, w0, w8
ret
tgt1(unsigned int):
sub sp, sp, #16
str w0, [sp, #12]
ldr w8, [sp, #12]
orr w8, w8, #0xf000000
str w8, [sp, #12]
ldr w8, [sp, #12]
orr w8, w8, #0xf0
str w8, [sp, #12]
ldr w0, [sp, #12]
add sp, sp, #16
ret
src2(unsigned int):
and w8, w0, #0xfffffff0
and w0, w8, #0xf00000ff
ret
tgt2(unsigned int):
sub sp, sp, #16
str w0, [sp, #12]
ldr w8, [sp, #12]
and w8, w8, #0xf00000ff
str w8, [sp, #12]
ldr w8, [sp, #12]
and w8, w8, #0xfffffff0
str w8, [sp, #12]
ldr w0, [sp, #12]
add sp, sp, #16
ret
src3(unsigned int):
mov w8, #240
movk w8, #61440, lsl #16
eor w0, w0, w8
ret
tgt3(unsigned int):
sub sp, sp, #16
str w0, [sp, #12]
ldr w8, [sp, #12]
eor w8, w8, #0xf0000000
str w8, [sp, #12]
ldr w8, [sp, #12]
eor w8, w8, #0xf0
str w8, [sp, #12]
ldr w0, [sp, #12]
add sp, sp, #16
ret