Messages in this thread | | | Date | Fri, 10 Apr 2015 11:48:32 -0700 | Subject | Re: [PATCH] x86: Align jump targets to 1 byte boundaries | From | Linus Torvalds <> |
| |
On Fri, Apr 10, 2015 at 5:50 AM, Denys Vlasenko <dvlasenk@redhat.com> wrote: > > However, I'm an -Os guy. Expect -O2 people to disagree :)
I used to be an -Os guy too. I'm a big believer in I$ density.
HOWEVER.
It turns out that gcc's -Os is just horrible nasty crap. It doesn't actually make good tradeoffs for code density, because it doesn't make any tradeoffs at all. It tries to choose small code, even when it's ridiculously bad small code.
For example, a 24-byte static memcpy is best done as three quad-word load/store pairs. That's very cheap, and not at all unreasonable.
But what does gcc do? It does a "rep movsl".
Seriously. That's *shit*. It absolutely kills performance on some very critical code.
I'm not making that up. Try "-O2" and "-Os" on the appended trivial code. Yes, the "rep movsl" is smaller, but it's incredibly expensive, particularly if the result is partially used afterwards.
And I'm not a hater of "rep movs" - not at all. I think that "rep movsb" is basically a perfect way to tell the CPU "do an optimized memcpy with whatever cache situation you have". So I'm a big fan of the string instructions, but only when appropriate. And "appropriate" here very much includes "I don't know the memory copy size, so I'm going to call out to some complex generic code that does all kinds of size checks and tricks".
Replacing three pairs of "mov" instructions with a "rep movs" is insane.
(There are a couple of other examples of that kind of issues with "-Os". Like using "imul $15" instead of single shift-by-4 and subtract. Again, the "imul" is certainly smaller, but can have quite bad latency and throughput issues).
So I'm no longer a fan of -Os. It disables too many obviously good code optimizations.
Linus
--- struct dummy { unsigned long a, b, c; };
void test(struct dummy *a, struct dummy *b) { *b = *a; }
| |