This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Mindless ABI adherence
- To: gcc-bugs at gcc dot gnu dot org
- Subject: Mindless ABI adherence
- From: "D. J. Bernstein" <djb at cr dot yp dot to>
- Date: 19 Oct 2001 04:08:09 -0000
- Automatic-Legal-Notices: Copyright 2001, D. J. Bernstein. My transmission of this message to you does not constitute a copyright waiver or any other limitation of my rights, even if you have told me otherwise.
- Cc: djb at cr dot yp dot to
Context: http://cr.yp.to/nistp224.html, a high-speed library for
elliptic-curve cryptography. I'll skip my usual comments about how bad
gcc is at scheduling floating-point code for real CPUs.
General problem: gcc blindly follows what ABIs say about alignment and
function calls, even when there is no reason for it to do so.
Suggestion #1: gcc should automatically align every global (text and
data and bss) variable of size 2^k (or an odd multiple of 2^k) to at
least a 2^k-byte boundary. A global double variable, for example, should
be 8-byte aligned by default on every architecture.
Some shortsighted ABIs say that doubles are 4-byte aligned. This is an
issue for struct organization and for stack organization. It is not an
issue for global variables. There is no excuse for underaligning a
global variable.
I started optimizing nistp224 for the PowerPC a few days ago. I was
astounded to see gcc screwing up the alignment of double-precision
variables under both MacOS X and AIX.
I don't want a PowerPC version of -malign-double. Frankly, I don't want
to have to use -malign-double for the x86. I want gcc to align all
global variables properly by default.
Suggestion #2, not quite as trivial: gcc should give the programmer a
reasonable level of control over alignment.
It would be very helpful to have a portable -falign-globals-6 option to
align all global variables to at least 64-byte boundaries, for example.
The assembler and linker will have to cooperate.
It would also be helpful to have a way to put a particular array at an
address that is, for example, 20000 modulo 65536, so that it doesn't
bump into the L1 cache lines for another array at address 40000 modulo
65536. The OS will shift everything by a random multiple of 4K when it
runs the program, but the arrays will still be separated.
Suggestion #3, substantially less trivial but still doable: gcc should
use a sane register allocation mechanism for static functions.
nistp224 has several static leaf functions taking a few hundred cycles
each. Right now, every function call wastes something like 40 cycles
saving and restoring f14 through f31 on the PowerPC. This adds up to at
least 117000 cycles, maybe more, on top of a computation that takes only
about 900000 cycles.
gcc should automatically use caller-save for static functions, at least
in the non-recursive case. It doesn't matter what the ABIs say. The
usual argument against making all registers caller-save, namely that the
caller has to save everything because it doesn't know what registers the
callee is using, has no relevance to static functions.
Similarly, even though the x86 ABI requires function arguments to be
passed on the stack, it's usually quite a bit faster to pass arguments
in registers. A small amount of work here would noticeably speed up a
huge number of programs.
---Dan