Mat Hostetter via llvm-dev
2021-Feb-11 13:29 UTC
[llvm-dev] [X86] How do I set just the low byte of an x86_64 register?
I work on a compiler that uses LLVM for its back end. I'm interested in
setting just the low byte of a register, leaving the other bits alone, for some
GC tag bit shenanigans, e.g.:
long replace_low_byte_with_37(long* a) {
return (*a & ~0xFFL) | 37;
}
x86_64 has a movb instruction that does exactly this, but I can't get clang
(or any other compiler), to use movb for this purpose, even at -Os.
Here is the -Os -march=sandybridge compiler output for gcc-10.2, icc-21.1.9, and
clang-11.0.1 (all different!), as well as how a simple movb assembles:
0000000000000000 <gcc>:
0: 48 8b 07 mov (%rdi),%rax
3: 30 c0 xor %al,%al
5: 48 83 c8 25 or $0x25,%rax
9: c3 retq
000000000000000a <icc>:
a: 48 8b 07 mov (%rdi),%rax
d: 48 25 00 ff ff ff and $0xffffffffffffff00,%rax
13: 48 83 c0 25 add $0x25,%rax
17: c3 retq
0000000000000018 <clang>:
18: 48 c7 c0 00 ff ff ff mov $0xffffffffffffff00,%rax
1f: 48 23 07 and (%rdi),%rax
22: 48 83 c8 25 or $0x25,%rax
26: c3 retq
0000000000000027 <simple_movb_by_hand>:
27: 48 8b 07 mov (%rdi),%rax
2a: b0 25 mov $0x25,%al
2c: c3 retq
As you can see, movb would be smallest (and llvm's is the biggest). Size is
important for my use case.
So why don't these compilers generate movb? Perhaps the concern is partial
register stalls and how %rax and %al interact with the register renamer. As I
understand the
background<https://stackoverflow.com/questions/45660139/how-exactly-do-partial-registers-on-haswell-skylake-perform-writing-al-seems-to>
from Peter Cordes referenced by
#34707<https://bugs.llvm.org/show_bug.cgi?id=34707>, the punchline is that
since Sandy Bridge, and especially Skylake, the partial register stall is no big
deal for an actual RMW operation like this.
But even on CPUs where there is a stall that's worse than the added
instructions from not using movb, -Os should still prefer movb.
I'm not advocating using this for %ah (etc.), which is famously
incorrect<http://gallium.inria.fr/blog/intel-skylake-bug/> in some Skylake
and Kaby Lake CPUs without a microcode patch.
Is there a way to get LLVM to generate movb to set just the low byte?
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20210211/71bdd072/attachment.html>
Tim Northover via llvm-dev
2021-Feb-11 18:13 UTC
[llvm-dev] [X86] How do I set just the low byte of an x86_64 register?
On Thu, 11 Feb 2021 at 13:29, Mat Hostetter via llvm-dev <llvm-dev at lists.llvm.org> wrote:> But even on CPUs where there is a stall that's worse than the added instructions from not using movb, -Os should still prefer movb.It doesn't really change anything (we still don't do movb), but Clang's real size optimization option is "-Oz". -Os is much closer to -O2 with just a hint of caring about size. Cheers. Tim.