This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
MMIX ABIs (was: Re: Status of the MMIX GCC port...)
- To: Phil Jensen <pjensen at columbus dot rr dot com>
- Subject: MMIX ABIs (was: Re: Status of the MMIX GCC port...)
- From: Hans-Peter Nilsson <hp at bitrange dot com>
- Date: Wed, 23 Feb 2000 21:26:25 -0500 (EST)
- cc: gcc at gcc dot gnu dot org, mmixmasters at leonora dot org
On Mon, 21 Feb 2000, Phil Jensen wrote:
> On Sun, 20 Feb 2000, Hans-Peter Nilsson wrote:
> > - An ABI is sketched. The ABI suggested by Knuth does not
> > fit exactly, but I'll add support to interface to code written
> > for that ABI.
>
> I don't understand this. It seems to me that the ABI implied by
> the Knuth docs should not need changing.
Not necessarily. I was trying to make a case for what I *think*
is a more optimal ABI: not just because GCC made me do it, but
because I *think* it is better.
> I am willing to believe that GCC doesn't understand the possibility
> of a register-stack architecture like this one, but it seems awful
> that such a gap in GCC's (present) world view should be used as a
> reason to disturb what, from an assembly-language programmer's
> point of view, is such an elegant design.
Somewhat elegant, but I also think it is suboptimal.
(To GCC folks: the register stackness is with *windows*, like
SPARC; not as i387).
> I strongly urge that the ABI you describe should be viewed as a
> stopgap, to allow testing of GCC in other respects, until someone
> delves deeply enough into GCC to get it to understand how MMIX is
> _intended_ to work.
I guess you did not see the flashing neon sign saying
"preliminary; work in progress; will change; not the whole
story, do not assume this is final". ;-)
If you're referring to passing parameters in $0 and up as
"intended", then right, that ABI *has* to be implemented, since
that's what's documented and what is expected to be there.
In *other* respects, what is intended, IMHO, doesn't matter, if
there's a more optimal solution.
What I proposed, or what anyone proposes, is for all I care
intermediate until there are measurements from real programs
giving a clear indication on what's good and what's not.
The only sure thing is that in the end GCC will be able to
generate code for (a superset of, or "extended", whatever you
call it) the ABI that Knuth wrote about. Other ABI:s might be
optional; I don't consider it's decided which ABI is the best.
> Again, I certainly mean no disparagement of the work you have done,
> and would like to learn more about why this architecture presents
> a problem for GCC.
It's not mainly the architecture, it's the Knuth ABI that
presents the (harder) problems for making a GCC port generating
optimal code. For what I know, these are some of the issues:
One is that GCC assumes outgoing parameters and incoming
function values are placed in registers with fixed numbers
(whether on a per-file or per-function basis). For the Knuth
ABI, they can start at any local register, and should be placed
-all other things equal- in low-numbered registers, to advance
the register window as little as possible and without the need
to clear intermediate registers. (Newly "opened" registers,
when going from "marginal" to "local", are cleared when a
higher-numbered register is written, which takes time.)
There's also an issue with registers-to-allocate being
partitioned in two fixed (per-function or per-file) sets: those
that are clobbered by a function call, and those that are not.
A third issue is that the registers most favorable to save ($0
and up) are used for incoming function parameters. Register
allocation parameters therefore must take into account what
parameters and return value the current function has, and has to
worry about whether or not to have a register holding an
incoming parameter value to instead "save" another value.
That's for starters.
Deciding whether a register being saved or clobbered is
"intended" for MMIX to be dynamic for each function-call within
the function: you put values you want to save in low registers,
then use the next higher register as the first outgoing
parameter register. Outgoing parameters and higher registers
are call-clobbered to the calling function.
To the called function, it is unimportant in which register
outgoing parameters start, as you use the X argument in PUSHJ to
move the register window so they appear incoming in $0. GCC
does not grok this dynamic situation currently: that a register
can be call-saved in one part of the function, and be
call-clobbered in another part, and be or not be a parameter
register differently for different calls within the function.
At least GCC can't be taught to do it without resorting to
"clever" tricks or rewriting parts of the register allocation
and alias analysis code.
One solution is to statically assign a set of registers (say,
$0..$15) to hold saved/incoming parameters/return-value
registers, and make those non-global registers above ($16..$31)
be outgoing-parameter registers and call-clobbered registers.
This should be combined with a late-stage renumbering: changing
$16.. to $(N+1).. where N is the last used call-saved register,
when some are not used.
However, this can't be as good as letting those numbers vary
dynamically, for each individual function call. Right now this
static assignment seems the only reasonable solution for the
Knuth ABI and GCC.
The ABI I proposed would not have these issues.
It would also use call-clobbered rather than call-saved
registers for incoming parameters, and use the same register for
function value and first parameter register, incoming as well as
outgoing. Those traits are what I believe is a win, unrelated
to limitations of GCC. For now, those beliefs are not anywhere
solid enough to ask Knuth to make changes or add notes: I don't
have anything more serious than a gut feeling and shoehorning of
findings reported in my master's thesis. (I guess those will be
hard-earned USD $2.56. :-)
The port is still in early stages of development:
=== gcc Summary ===
# of expected passes 8023
# of unexpected failures 766
# of unexpected successes 1
# of expected failures 24
# of unresolved testcases 368
# of unsupported tests 35
/gcc/xgcc version 2.96 20000220 (experimental)
(Executing executable tests, some fails due to many missing
library functions.)
brgds, H-P