
MODULE 38 – Code Improving Transformations We will start this module by looking at use-define chains and define-use chains. We shall also discuss the algorithms for global common sub-expression, copy propagation and loop optimizations. 38.1 Define-Use and Use-Define (DU/UD) Chains After understanding the various algorithms to identify reaching definitions, available expressions and live-variable analysis in the previous module, we will discuss yet another procedure that is helpful for optimization in this module using define-use and use-define chains. The define-use (du) and use-define (ud) chains are convenient way to access/use reaching definition information. Def-Use chains (DU chains) gives information of the possible consumers of the definition produced for a given a def. Use-Def chains (UD chains), accepts a use, and identifies all the possible producers of the definition consumed. Consider the example given in figure 38.1 having a control flow as depicted with variables r1 to r8. Figure 38.1 Example flow graph for DU / UD chain computation In figure 38.1, the variables r1 is defined at definition 1. This variable is used at definitions 3, 4. At definition 4, the variable r1 is redefined and is used at definition 12. Thus DU chain of variable r1 has to be stated in the context of definitions at (1) and (4) respectively. Table 38.1 gives the DU and UD chains of some variables. Table 38.1 DU and UD chains of some variables Variable DU chain UD chain Comments r1 (1) 3,4 (12) 11 Defined at (1) is used at (3) and (4). Redefinition at (4) 5 (4) is used at (5). (11) (12) is not part of the chain as it creates a new definition for r1. This can be considered as part of the UD chain r3 (3) 11 (6) (5) Defined at (3) is used at (11) if it follows one path. (5) 11 Defined at (3) is redefined at (5) and thus the (12) -> definition at (5) could be used at (11). However what is used at (6) is the definition at (5) r7 (7) (9) (10) 6,9 Defined at (7) is used at (9). The value used at (10) could be from either the definition of (6) or (9) Based on this UD and DU chains, we can identify Next-use information, available expressions and reaching definitions information for carrying out function preserving transformations. 38.2 Global Common Sub-expression elimination The Available expression algorithm discussed in the previous module computes and informs whether an expression is common at point ‘p’. After identifying this, we need to get rid of the common sub-expression, both locally and globally. Algorithm 38.1 briefs on the procedure for global common sub-expression elimination. Algorithm 38.1 • Input: A flow graph with available expression information • Output: A revised flow graph Eliminate_Common_sub_expression() { For every statement‘s’ of the form x:=y+z if y+z is available at the beginning of ‘s’ do the following • Search backward from ‘s’ the expression ‘y+z’ • Create a new variable ‘u’ • Replace each statement w:=y+z found in the previous step by • u := y+z • w:= u • Replace statement ‘s’ by x := u } Observations of the algorithm: Searching for ‘y+z’ can be done as a data-flow analysis problem. The replacement need not be optimized as it could result in copy statements. This algorithm does not handle the transitive nature of common sub-expressions. Consider the following two statements: – a := x+y vs c := x+y – b := a*z d := c*z In the above set of statements, the value of ‘b’ and‘d’ are also essentially same and the above algorithm does not handle this situation. Consider the example of figure 38.2, to apply the common sub-expression elimination algorithm. Figure 38.2 Example for global common sub-expression elimination From figure 38.2, the algorithm identifies 4*i as a common sub-expression and creates a new variable ‘u’. Then the expression is replaced with ‘u’. This algorithm could also be adopted if the representation of three-address code is done on a value-numbering based method. In this method, the line number of the first appearing common expression is used in other places. For example, in the same flow graph of figure 38.2, if the expression “4*i" is at line (15), then line (15) is used wherever 4 * i is identified as a common expression. Thus for the example of figure 38.2, the value numbering based method of global common sub-expression elimination is given in figure 38.3. Figure 38.3 Value numbering based method of optimization. 38.3 Copy Propagation As we discussed in the previous module, copies gets generated due to elimination of common sub-expression. Consider the following statement ‘S’ that assigns the variable, • S: x:= y After this assignment, the value of ‘x’ and ‘y’ will be exactly identical. So, we could get rid of variable ‘x’ and use ‘y’ in place of ‘x’. To carry out this, we initially determine where the value of ‘x’ is used and substitute ‘y’ in place of ‘x’ where ‘u’ is a statement that uses ‘y’. We need to ensure that statement ‘s’ must be the only definition of ‘x’ reaching ‘u’ and this could be checked using UD chains. We also need to ensure, that on every path from‘s’ to ‘u’, there are no assignments to ‘y’ which could be looked upon as a new data-flow analysis problem. The procedure that is discussed to eliminate copy propagation can be looked upon as forward copy propagation procedure which looks at the RHS of an assignment statement. However, this does not consider the chain of dependencies and hence create dead code. As an example for copy propagation, figure 38.4 is used. Figure 38.4 Copy propagation As given in given in figure 38.4, r1 and r2 have the same values. So, we replace r2 in place of r1. After performing copy propagation, the statement r1 := r2 remains as a dead code. The following are some of the data flow equations that could be defined and used to identify copy propagation. Here, c_gen[] and c_kill[] indicates the copies generated and killed in a basic block. Thus • out[B] = c_gen[B] U (in[B] – c_kill[B]) – Similar to reaching definitions • in[B] = ∩ out[P] where P is a predecessor block- Intersection of all the predecessor’s output is computed as the in[] of all but the first block. • in[B1] = Φ where B1 is the initial block The algorithm is similar to available expressions algorithm and the computation are also same. Consider the example given in figure 38.5 to identify copy propagation. Figure 38.5 Example of copy propagation The following are the computations of the various data flow parameters. c_gen [B1] = {x := y } c_gen[B3] = { x:= z} c_kill [ B2] = {x:= y} c_kill[B1] = {x:=z} c_kill[B3] = {x := y} All other c_gen and c_kill are Φ No copy of x:=y or x:= z reaches B5 and thus there is no optimization necessary with respect to copy propagation identification and elimination. Algorithm 38.2 elucidates the copy propagation algorithm based on the above discussed procedure. Algorithm 38.2 - Copy Propagation • Input: A flow graph with ud-chains and c_in[B], du-chains that has the use of all definitions • Output: revised flow graph IdentifyandRemove_CopyPropagation { For each copy ‘s’ x:=y, do the following Determine the uses of ‘x’ that are reached by this definition • Determine whether for every use of ‘x’, ‘s’ is in c_in[B] where B is the block for this use and no definitions of ‘x’ or ‘y’ occur prior to this use • If the statement meets this condition, remove ‘s’ and replace all uses of ‘x’ by ‘y’ } Thus eliminating copy propagation would result in dead code. 38.4 Constant Propagation Another important optimization to be considered is constant propagation. Similar to copy propagation, if a variable is assigned a constant and if the variable is used in subsequent expression, it can be replaced by the constant thus making the assignment of the constant to the variable as dead code. Consider the forward propagation of assignment of the form d: rx := L where L is literal and rx is a variable. Constant propagation involves replacement of “rx” with “L” wherever possible, provided the definition’s’ is available at point of replacement. 38.5 Unreachable Code Elimination Copy propagation and constant folding could result in dead code. In addition, as discussed in peep hole optimization, some sections of code may be unreachable. This unreachable code need to be eliminated. To eliminate this, algorithm 38.3 is used. Algorithm 38.3 – Unreachable code elimination. Input: Flow graph Output: Revised flow graph Eliminate_Notreachable_code { Mark initial BB visited to_visit = initial BB while (to_visit not empty) current = to_visit.pop() for each successor block of current Mark successor as visited; to_visit += successor endfor endwhile Eliminate all unvisited blocks } The algorithm carries out a depth-first search and tries to identify blocks that are useful. After identifying useful blocks, the other blocks available in the flow graph are identified as not useful. Figure 38.6 Unreachable code elimination Consider figure 38.6, which involves 5 basic blocks. As can be seen, a depth-first search from the entry point would include bb1, then bb4 followed by bb2 and then bb5. The block bb3 is never to be reached and hence could be eliminated. 38.6 Loop invariant computation The three major loop optimization techniques are strength reduction, code motion and induction variable elimination.
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages9 Page
-
File Size-