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.
 | |
| 
 |