Code Generation
SINI ANNA ALEX
Loops
Loops of the Flow Graph
Next Use Information
Knowing when the value of a variable will be used next is essential for generating
good code. If the value of a variable that is currently in a register will never be
referenced subsequently, then that register can be assigned to another variable.
Wish to determine for each three-address statement x = y + z what the next uses
of x, y, and z are. For the present, we do not concern ourselves with uses outside
the basic block containing this three-address statement.
There is an algorithm to determine liveness and next-use information makes a
backward pass over each basic block.
We store the information in the symbol table.
Next Use Information
Optimization of Basic Blocks
We can often obtain a substantial improvement in the running time of code
merely by performing local optimization within each basic block by itself.
More thorough global optimization, which looks at how information flows
among the basic blocks of a program.
The DAG Representation of Basic
Blocks
Construct a DAG for a basic block as follows:
1. There is a node in the DAG for each of the initial values of the variables appearing
in the basic block.
2. There is a node N associated with each statement s within the block. The children
of N are those nodes corresponding to statements that are the last definitions, prior
to s, of the operands used by s.
3. Node N is labeled by the operator applied at s, and also attached to N is the list of
variables for which it is the last definition within the block.
4. Certain nodes are designated output nodes. These are the nodes whose variables
are live on exit from the block; that is, their values may be used later, in another
block of the flow graph.
The DAG Representation of Basic
Blocks
The DAG representation of a basic block lets us perform several code improving
transformations on the code represented by the block.
a) We can eliminate local common subexpressions, that is, instructions that compute
a value that has already been computed.
b) We can eliminate dead code, that is, instructions that compute a value that is
never used.
c) We can reorder statements that do not depend on one another; such reordering
may reduce the time a temporary value needs to be preserved in a register.
d) We can apply algebraic laws to reorder operands of three-address instructions,
and sometimes thereby simplify the computation.
The DAG Representation of Basic
Blocks
DAG for Basic
Block
Finding Local Common
Subexpressions
If b is not live on exit from the block
If b and d both is live on exit from the block
Dead Code Elimination
The operation on DAG's that corresponds to dead-code elimination can be implemented as
follows. We delete from a DAG any root (node with no ancestors) that has no live variables
attached. Repeated application of this transformation will remove all nodes from the DAG that
correspond to dead code.
If a and b are live but c and e are not, we can immediately remove the root labeled e. Then,
the node labeled c becomes a root and can be removed. The roots labeled a and b remain,
since they each have live variables attached.
Use of Algebraic Identities
1) Algebraic identities represent important class of optimizations on basic
blocks.
3) Constant folding - A third class of
related optimizations is constant
2) Another class of algebraic optimizations folding. Here we evaluate constant
includes local reduction in strength, that is, expressions at compile time and
replacing a more expensive operator by a replace the constant expressions by
cheaper one as in: their values.
Thus the expression 2 * 3.14
would be replaced by 6.28.
Reorder of statements
The following intermediate code might be generated:
If t is not needed outside this block, we can change this sequence
to
Representation of Array References
Representation of Array References