78 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			78 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
.NH 2
 | 
						|
Implementation
 | 
						|
.PP
 | 
						|
UD first builds a number of tables:
 | 
						|
.IP locals: 9
 | 
						|
contains information about the local variables of the
 | 
						|
current procedure (offset,size,whether a register message was found
 | 
						|
for it and, if so, the score field of that message)
 | 
						|
.IP defs:
 | 
						|
a table of all explicit definitions appearing in the
 | 
						|
current procedure.
 | 
						|
.IP copies:
 | 
						|
a table of all copies appearing in the
 | 
						|
current procedure.
 | 
						|
.LP
 | 
						|
Every variable (local as well as global), definition and copy
 | 
						|
is identified by a unique number, which is the index
 | 
						|
in the table.
 | 
						|
All tables are constructed by traversing the EM code.
 | 
						|
A fourth table, "vardefs" is used, indexed by a 'variable number',
 | 
						|
which contains for every variable the set of explicit definitions of it.
 | 
						|
Also, for each basic block b, the set CHGVARS containing all variables
 | 
						|
changed by it is computed.
 | 
						|
.PP
 | 
						|
The GEN sets are obtained in one scan over the EM text,
 | 
						|
by analyzing every EM instruction.
 | 
						|
The KILL set of a basic block b is computed by looking at the
 | 
						|
set of variables
 | 
						|
changed by b (i.e. CHGVARS[b]).
 | 
						|
For every such variable v, all explicit definitions to v
 | 
						|
(i.e. vardefs[v]) that are not in GEN[b] are added to KILL[b].
 | 
						|
Also, the implicit defininition of v is added to KILL[b].
 | 
						|
Next, the data flow equations for use-definition information
 | 
						|
are solved,
 | 
						|
using a straight forward, iterative algorithm.
 | 
						|
All sets are represented as bitvectors, so the operations
 | 
						|
on sets (union, difference) can be implemented efficiently.
 | 
						|
.PP
 | 
						|
The C_GEN and C_KILL sets are computed simultaneously in one scan
 | 
						|
over the EM text.
 | 
						|
For every copy A := B appearing in basic block b we do
 | 
						|
the following:
 | 
						|
.IP 1.
 | 
						|
for every basic block n /= b that changes B, see if the definition A := B
 | 
						|
reaches the beginning of n (i.e. check if the index number of A := B in
 | 
						|
the "defs" table is an element of IN[n]);
 | 
						|
if so, add the copy to C_KILL[n]
 | 
						|
.IP 2.
 | 
						|
if B is redefined later on in b, add the copy to C_KILL[b], else
 | 
						|
add it to C_GEN[b]
 | 
						|
.LP
 | 
						|
C_IN and C_OUT are computed from C_GEN and C_KILL via the second set of
 | 
						|
data flow equations.
 | 
						|
.PP
 | 
						|
Finally, in one last scan all opportunities for optimization are
 | 
						|
detected.
 | 
						|
For every use u of a variable A, we check if
 | 
						|
there is a unique explicit definition d reaching u.
 | 
						|
.sp
 | 
						|
If the definition is a copy A := B and B has the same value at d as
 | 
						|
at u, then the use of A at u may be changed into B.
 | 
						|
The latter condition can be verified as follows:
 | 
						|
.IP -
 | 
						|
if u and d are in the same basic block, see if there is
 | 
						|
any assignment to B in between d and u
 | 
						|
.IP -
 | 
						|
if u and d are in different basic blocks, the condition is
 | 
						|
satisfied if there is no assignment to B in the block of u prior to u
 | 
						|
and d is in C_IN[b].
 | 
						|
.LP
 | 
						|
Before the transformation is actually done, UD first makes sure the
 | 
						|
alteration is really desirable, as described before.
 | 
						|
The information needed for this purpose (access costs of local and
 | 
						|
global variables) is read from a machine descriptor file.
 | 
						|
.sp
 | 
						|
If the only definition reaching u has the form "A := constant", the use
 | 
						|
of A at u is replaced by the constant.
 | 
						|
 |