Register Classes¶
Overview¶
Two views of registers are used throughout the compiler: generic registers and machine registers. To facilitate retargeting, several classes of generic registers are defined to hide the machine registers from various phases of the compiler. Generic registers are mapped to machine registers with the likelihood that more than one class of generic registers map to a single class of machine registers. A generic register class exists for each of the register types seen by the ILI: address register, integer register (integers, booleans, char, etc.), single precision register, and double precision register. The generic register mappings are primarily used by the expander and optimizer when assigning global registers.
Depending on the target register numbers, when used as operands to ILI, reflect either actual machine register numbers or numbers which are mapped by the code scheduler to actual machine numbers. Registers can be used as arguments for calling intrinsics, and as operands to register define and move ILI. In the latter case, these ILI are typically generated by the expander and optimizer when registers have been assigned globally.
Data Structures¶
Machine Register Table¶
The target machine registers are divided into classes appropriate for the target’s architecture. Each machine register set has the following properities:
each class is expressed as a set of increasing order of numbers.
the scratch registers are defined by the code scheduler
the global registers are allocated either in decreasing or increasing order from a given point.
the scratch registers that can be changed by a procedure and intrinsic.
A machine register table is used to define the classes of machine registers, where there is one entry for each class. A table entry is defined by the following C structure declaration:
typedef struct {
char min;
char max;
char first_global;
char last_global;
char next_global;
char nused;
} MACH_REG;
min
minimum register number of the set.
max
maximum register number of the set (the set is defined by the closed interval
[min..max]
).first_global
the first register number that can be global register.
last_global
the last register number that can be global.
next_global
the next register number that can be globally assigned. In the event that not all of the registers in the global set are assigned by the expander or optimizer, the scheduler may use the global registers not assigned as scratch registers.
nused
the number of global registers assigned by the expander or optimizer.
All but the fields next_global
and nused
are statically
initialized; next_global
and nused
are modified when registers are allocated globally
during the expander and optimizer phases.
It is possible that a machine’s registers cannot be expressed
as the closed interval [min .. max]
.
If this occurs, the machine register table will describe
“pseudo” machine registers which adhere to the above properties.
These pseudo machine registers would be mapped to the actual machine registers.
The ILI, expander, and optimizer would still refer to the registers from
the machine register table.
The scheduler would use the pseudo to machine register mapping when it’s
neccessary to refer to an actual machine register.
Generic Register Table¶
The generic registers are divided into classes of registers which correspond to the types of the registers seen by the ILI. The mapping of generic registers to machine registers is described in the generic register table. Each table entry not only describes the mapping but provides information regarding global register allocation. Each table entry is defined by the following C structure declaration:
typedef struct {
char max;
char nused;
char joined;
int rcand;
MACH_REG \*mach_reg;
INT const_flag;
} REG;
max
the maximum number of registers that can be globally assigned.
nused
the number of registers globally assigned.
joined
flag indicating that the registers are formed from multiple machine registers.
rcand
list of global register candidates.
mach_reg
pointer to the machine register table entry of the machine registers to which the generic class maps.
const_flag
a flag word which controls the assignment of constants to registers. The fields
max
,joined
,mach_reg
, andconst_flag
are statically initialized; fieldsnused
andrcand
in module machreg.c are modified when registers are allocated globally during the expander and optimizer phases.
Processing¶
The file
machreg.h
contains the specifics for the target machine’s registers such as
definitions for the mach_reg
structure, external declarations for the functions used to access
the structure, and
macro definitions used to represent various pieces of the machine
registers.
When constructing
machreg.h,
certain macros must be present:
those which deal with register arguments and
those which describe the machine registers.
Argument macros are present which provided the register numbers for
accessing
argument
registers
where the arguments to the macros are machine dependent.
There is one macro for each register type:
- AR(i)
define an address register
- IR(i)
define a integer register
- SP(i)
define a single precision register for argument
- DP(i)
define a double precision register for argument
- ISP(i)
define a single precision register for an imaginary argument
- IDP(i)
define a double precision register for an imaginary argument
Machine Register Macros¶
Special macros are used for defining the global registers in each
of the unique register classes (the macro
MR_UNIQ
gives the number of unique classes).
For each global set, the lower and upper bounds are specified in the
form
MR_L<i>
to
MR_U<i>
,
where <i> = 1 to
MR_UNIQ
.
For example, if there are 2 unique classes, then the interval defined
by macros
MR_L1
to
MR_U1
defines
the global registers for set 1 and macros
MR_L2
to
MR_U2
defines
the global registers for set 2.
Note that the file
machregdf.h
uses these macros to data initialize the
mach_reg
table.
The macro,
MR_NUMGLB
,
defines the total number of global registers for the machine.
This macro is used by the optimizer to declare space for its
global register history data structures.
The macro GR_THRESHOLD defines the count which a candidate must exceed before it’s assigned a register.
Program Units¶
The register module is composed of the C files register.c and machreg.c. The file register.c contains the following routines:
void reg_init()
This function initializes the register information for a function or subprogram which is passed on to the code generator and assembler.
void addrcand(ili)
int ili;
Add an ili to its register candidate list.
void dmprcand()
Dump the register candidate lists.
void dmprat(rat)
int rat;
Dump the register assigned table indexed by
rat
.
int getrcand(candl)
int candl;
Gets a register candidate for the list
candl
.
void storedums(bih, rat)
int bih, rat;
Generates stores of the registers in the table ```` assigned to Fortran dummy arguments. These stores are added to the block located by the block information header,
bih
.
void mkrtemp_init()
Initialize the register temporary areas; this is done when unique temps are desired during the processing of a unit (i.e., for an ILM block) but are still shared with the previous unit.
int mkrtemp(ili)
int ili;
Gets a register temporary whose register type is based on the type of
ili
.
void mkrtemp_end()
Routine called at the end of processing a function to so that the temps created for the next function are unique.
void mkrtemp_update(rtemp)
short rtemp[];
Update the maximum values for the register temporaries whose information is stored in
rtemp
.
void mkrtemp_copy(rtemp)
short rtemp[];
Copy the maximum values of the temporaries which have been allocated to the area
rtemp
.
int assn_rtemp(ili)
int ili;
Create a register temporary for
ili
and record the temporary and the ili in the appropriate register candidate list.
.The file machreg.c contains the following routines:
void mr_init()
This function initializes the fields of the structures,
mach_reg
andreg
, for the current function or subprogram which are not statically initialized.
int mr_getreg(rtype)
int rtype;
This function returns a global machine register number for the register type specified by
rtype
. If one is not available,MR_NOREG
is returned.
int mr_gindex(rtype, reg)
int rtype, reg;
This function maps a register type,
rtype
, and a global machine register number,reg
, to an index value in the range0..MR_NUMGLB-1
. This routine is aware that certain register types may map to the same machine register set. This routine provides a mechanism for ensuring that the history of a machine register can be kept regardless of the many to one register type mapping.