139 lines
		
	
	
	
		
			5.7 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			139 lines
		
	
	
	
		
			5.7 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| .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.
 |