Initial revision
This commit is contained in:
139
doc/ego/ra/ra2
Normal file
139
doc/ego/ra/ra2
Normal file
@@ -0,0 +1,139 @@
|
||||
.NH 2
|
||||
Usage of registers in ACK compilers
|
||||
.PP
|
||||
We will first describe the major design decisions
|
||||
of the Amsterdam Compiler Kit,
|
||||
as far as they concern register allocation.
|
||||
Subsequently we will outline
|
||||
the role of the Global Optimizer in the register
|
||||
allocation process and the interface
|
||||
between the code generator and the optimizer.
|
||||
.NH 3
|
||||
Usage of registers without the intervention of the Global Optimizer
|
||||
.PP
|
||||
Registers are used for two purposes:
|
||||
.IP 1.
|
||||
for the evaluation of arithmetic expressions
|
||||
.IP 2.
|
||||
to hold local variables, for the duration of the procedure they
|
||||
are local to.
|
||||
.LP
|
||||
It is essential to note that no translation part of the compilers,
|
||||
except for the code generator, knows anything at all
|
||||
about the register set of the target computer.
|
||||
Hence all decisions about registers are ultimately made by
|
||||
the code generator.
|
||||
Earlier phases of a compiler can only \fIadvise\fR the code generator.
|
||||
.PP
|
||||
The code generator splits the register set into two:
|
||||
a fixed part for the evaluation of expressions (called \fIscratch\fR
|
||||
registers) and a fixed part to store local variables.
|
||||
This partitioning, which depends only on the target computer, significantly
|
||||
reduces the complexity of register allocation, at the penalty
|
||||
of some loss of code quality.
|
||||
.PP
|
||||
The code generator has some (machine-dependent) knowledge of the access costs
|
||||
of memory locations and registers and of the costs of saving and
|
||||
restoring registers. (Registers are always saved by the \fIcalled\fR
|
||||
procedure).
|
||||
This knowledge is expressed in a set of procedures for each target machine.
|
||||
The code generator also knows how many registers there are and of
|
||||
which type they are.
|
||||
A register can be of type \fIpointer\fR, \fIfloating point\fR
|
||||
or \fIgeneral\fR.
|
||||
.PP
|
||||
The front ends of the compilers determine which local variables may
|
||||
be put in a register;
|
||||
such a variable may never be accessed indirectly (i.e. through a pointer).
|
||||
The front end also determines the types and sizes of these variables.
|
||||
The type can be any of the register types or the type \fIloop variable\fR,
|
||||
which denotes a general-typed variable that is used as loop variable
|
||||
in a for-statement.
|
||||
All this information is collected in a \fIregister message\fR in
|
||||
the EM code.
|
||||
Such a message is a pseudo EM instruction.
|
||||
This message also contains a \fIscore\fR field,
|
||||
indicating how desirable it is to put this variable in a register.
|
||||
A front end may assign a high score to a variable if it
|
||||
was declared as a register variable (which is only possible in
|
||||
some languages, such as "C").
|
||||
Any compiler phase before the code generator may change this score field,
|
||||
if it has reason to do so.
|
||||
The code generator bases its decisions on the information contained
|
||||
in the register message, most notably on the score.
|
||||
.PP
|
||||
If the global optimizer is not used,
|
||||
the score fields are set by the Peephole Optimizer.
|
||||
This optimizer simply counts the number of occurrences
|
||||
of every local (register) variable and adds this count
|
||||
to the score provided by the front end.
|
||||
In this way a simple, yet quite effective
|
||||
register allocation scheme is achieved.
|
||||
.NH 3
|
||||
The role of the Global Optimizer
|
||||
.PP
|
||||
The Global Optimizer essentially tries to improve the scheme
|
||||
outlined above.
|
||||
It uses the following principles for this purpose:
|
||||
.IP -
|
||||
Entities are not always assigned a register for the duration
|
||||
of an entire procedure; smaller regions of the program text
|
||||
may be considered too.
|
||||
.IP -
|
||||
several variables may be put in the same register simultaneously,
|
||||
provided at most one of them is live at any point.
|
||||
.IP -
|
||||
besides local variables, other entities (such as constants and addresses of
|
||||
variables and procedures) may be put in a register.
|
||||
.IP -
|
||||
more accurate cost estimates are used.
|
||||
.LP
|
||||
To perform its task, the optimizer must have some
|
||||
knowledge of the target machine.
|
||||
.NH 3
|
||||
The interface between the register allocator and the code generator
|
||||
.PP
|
||||
The RA phase of the optimizer must somehow be able to express its
|
||||
decisions.
|
||||
Such decisions may look like: 'put constant 1283 in a register from
|
||||
line 12 to line 40'.
|
||||
To be precise, RA must be able to tell the code generator to:
|
||||
.IP -
|
||||
initialize a register with some value
|
||||
.IP -
|
||||
update an entity from a register
|
||||
.IP -
|
||||
replace all occurrences of an entity in a certain region
|
||||
of text by a reference to the register.
|
||||
.LP
|
||||
At least three problems occur here: the code generator is only used to
|
||||
put local variables in registers,
|
||||
it only assigns a register to a variable for the duration of an entire
|
||||
procedure and it is not used to have some earlier compiler phase
|
||||
make all the decisions.
|
||||
.PP
|
||||
All problems are solved by one mechanism, that involves no changes
|
||||
to the code generator.
|
||||
With every (non-scratch) register R that will be used in
|
||||
a procedure P, we associate a new variable T, local to P.
|
||||
The size of T is the same as the size of R.
|
||||
A register message is generated for T with an exceptionally high score.
|
||||
The scores of all original register messages are set to zero.
|
||||
Consequently, the code generator will always assign precisely those new
|
||||
variables to a register.
|
||||
If the optimizer wants to put some entity, say the constant 1283, in
|
||||
a register, it emits the code "T := 1283" and replaces all occurrences
|
||||
of '1283' by T.
|
||||
Similarly, it can put the address of a procedure in T and replace all
|
||||
calls to that procedure by indirect calls.
|
||||
Furthermore, it can put several different entities in T (and thus in R)
|
||||
during the lifetime of P.
|
||||
.PP
|
||||
In principle, the code generated by the optimizer in this way would
|
||||
always be valid EM code, even if the optimizer would be presented
|
||||
a totally wrong description of the target computer register set.
|
||||
In practice, it would be a waste of data as well as text space to
|
||||
allocate memory for these new variables, as they will always be assigned
|
||||
a register (in the correct order of events).
|
||||
Hence, no memory locations are allocated for them.
|
||||
For this reason they are called pseudo local variables.
|
||||
Reference in New Issue
Block a user