0% found this document useful (0 votes)
10 views

Unit 6 and 7- Code Optimization and Code Generation

Uploaded by

btechgaming05
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views

Unit 6 and 7- Code Optimization and Code Generation

Uploaded by

btechgaming05
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 48

CE442: DESIGN OF LANGUAGE PROCESSOR

Unit-6 & 7

Code Optimization and Code Generation


Outline
• Compiler must do the storage allocation and
provide access to variables and data
• Memory management
– Stack allocation
– Heap management
– Garbage collection

Unit-6 & 7
Storage Organization

Unit-6 & 7
Static vs. Dynamic Allocation
• Static: Compile time, Dynamic: Runtime allocation
• Many compilers use some combination of
following
– Stack storage: for local variables, parameters and so on
– Heap storage: Data that may outlive the call to the
procedure that created it
• Stack allocation is a valid allocation for procedures
since procedure calls are nested

Unit-6 & 7
Sketch of a quicksort program

Unit-6 & 7
Activation for Quicksort

Unit-6 & 7
Activation tree representing calls during an
execution of quicksort

Unit-6 & 7
Activation records
• Procedure calls and returns are usaully managed
by a run-time stack called the control stack.
• Each live activation has an activation record
(sometimes called a frame)
• The root of activation tree is at the bottom of
the stack
• The current execution path specifies the content
of the stack with the last activation has record in
the top of the stack.
Unit-6 & 7
A General Activation Record

Unit-6 & 7
Downward-growing stack of activation records

Unit-6 & 7
Designing Calling Sequences
• Values communicated between caller and callee are
generally placed at the beginning of callee’s
activation record
• Fixed-length items: are generally placed at the
middle
• Items whose size may not be known early enough:
are placed at the end of activation record
• We must locate the top-of-stack pointer judiciously:
a common approach is to have it point to the end of
fixed length fields.
Unit-6 & 7
Division of tasks between caller and callee

Unit-6 & 7
calling sequence
• The caller evaluates the actual parameters
• The caller stores a return address and the old
value of top-sp into the callee's activation
record.
• The callee saves the register values and other
status information.
• The callee initializes its local data and begins
execution.

Unit-6 & 7
corresponding return sequence
• The callee places the return value next to the
parameters
• Using information in the machine-status field, the
callee restores top-sp and other registers, and then
branches to the return address that the caller
placed in the status field.
• Although top-sp has been decremented, the caller
knows where the return value is, relative to the
current value of top-sp; the caller therefore may
use that value.
Unit-6 & 7
Access to dynamically allocated arrays

Unit-6 & 7
ML
• ML is a functional language
• Variables are defined, and have their
unchangeable values initialized, by a statement
of the form:
val (name) = (expression)

• Functions are defined using the syntax:


fun (name) ( (arguments) ) = (body)

• For function bodies we shall use let-statements


of the form:
let (list of definitions) in (statements) end

Unit-6 & 7
A version of quicksort, in ML style, using
nested functions

Unit-6 & 7
Access links for finding nonlocal data

Unit-6 & 7
Sketch of ML program that uses function-
parameters

Unit-6 & 7
Actual parameters carry their access link
with them

Unit-6 & 7
Maintaining the Display

Unit-6 & 7
Maintaining the Display (Cont.)

Unit-6 & 7
Memory Manager
• Two basic functions:
– Allocation
– Deallocation
• Properties of memory managers:
– Space efficiency
– Program efficiency
– Low overhead

Unit-6 & 7
Typical Memory Hierarchy Configurations

Unit-6 & 7
Locality in Programs
The conventional wisdom is that programs spend 90%
of their time executing 10% of the code:
• Programs often contain many instructions that are
never executed.
• Only a small fraction of the code that could be
invoked is actually executed in a typical run of the
program.
• The typical program spends most of its time
executing innermost loops and tight recursive cycles
in a program.
Unit-6 & 7
Part of a Heap

Unit-6 & 7
Basic blocks and flow graphs
• Partition the intermediate code into basic blocks
– The flow of control can only enter the basic block
through the first instruction in the block. That is,
there are no jumps into the middle of the block.
– Control will leave the block without halting or
branching, except possibly at the last instruction in
the block.
• The basic blocks become the nodes of a flow
graph
Rules for finding leaders
• The first three-address instruction in the
intermediate code is a leader.
• Any instruction that is the target of a
conditional or unconditional jump is a leader.
• Any instruction that immediately follows a
conditional or unconditional jump is a leader.
Intermediate code to set a 10*10 matrix to
an identity matrix
Flow graph based on Basic Blocks
liveness and next-use information
• We wish to determine for each three address
statement x=y+z what the next uses of x, y and z are.
• Algorithm:
– Attach to statement i the information currently found in
the symbol table regarding the next use and liveness of x,
y, and z.
– In the symbol table, set x to "not live" and "no next use.“
– In the symbol table, set y and z to "live" and the next uses
of y and z to i.
DAG representation of basic blocks
• There is a node in the DAG for each of the initial values
of the variables appearing in the basic block.
• 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.
• 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.
• Certain nodes are designated output nodes. These are
the nodes whose variables are live on exit from the
block.
Code improving transformations
• We can eliminate local common subexpressions, that
is, instructions that compute a value that has already
been computed.
• We can eliminate dead code, that is, instructions that
compute a value that is never used.
• 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.
• We can apply algebraic laws to reorder operands of
three-address instructions, and sometimes t hereby
simplify t he computation.
DAG for basic block
DAG for basic block
array accesses in a DAG
• An assignment from an array, like x = a [i], is represented by creating
a node with operator =[] and two children representing the initial
value of the array, a0 in this case, and the index i. Variable x
becomes a label of this new node.
• An assignment to an array, like a [j] = y, is represented by a new
node with operator []= and three children representing a0, j and y.
There is no variable labeling this node. What is different is that the
creation of this node kills all currently constructed nodes whose
value depends on a0. A node that has been killed cannot receive
any more labels; that is, it cannot become a common
subexpression.
DAG for a sequence of array assignments
Rules for reconstructing the basic block

from a DAG
The order of instructions must respect the order of nodes in the DAG. That
is, we cannot compute a node's value until we have computed a value for
each of its children.
• Assignments to an array must follow all previous assignments to, or
evaluations from, the same array, according to the order of these
instructions in the original basic block.
• Evaluations of array elements must follow any previous (according to the
original block) assignments to the same array. The only permutation
allowed is that two evaluations from the same array may be done in either
order, as long as neither crosses over an assignment to that array.
• Any use of a variable must follow all previous (according to the original
block) procedure calls or indirect assignments through a pointer.
• Any procedure call or indirect assignment through a pointer must follow
all previous (according to the original block) evaluations of any variable.
Characteristic of peephole optimizations

• Redundant-instruction elimination
• Flow-of-control optimizations
• Algebraic simplifications
• Use of machine idioms
Redundant-instruction elimination
• LD a, R0
ST R0, a
• if debug == 1 goto L1
goto L2
L I : print debugging information
L2:
Flow-of-control optimizations

goto L1 if a<b goto L1


... ...
Ll: goto L2 Ll: goto L2

Can be replaced by:


Can be replaced
if a<b goto L2
by:
...
goto L2
Ll: goto L2
...
Ll: goto L2
Algebraic simplifications

• x=x+0

• x=x*1
Register Allocation and Assignment

• Global Register Allocation


• Usage Counts
• Register Assignment for Outer Loops
• Register Allocation by Graph Coloring
Global register allocation
• Previously explained algorithm does local (block based)
register allocation
• This resulted that all live variables be stored at the end of
block
• To save some of these stores and their corresponding
loads, we might arrange to assign registers to frequently
used variables and keep these registers consistent across
block boundaries (globally)
• Some options are:
– Keep values of variables used in loops inside registers
– Use graph coloring approach for more globally allocation
Usage counts
• For the loops we can approximate the saving
by register allocation as:
– Sum over all blocks (B) in a loop (L)
– For each uses of x before any definition in the
block we add one unit of saving
– If x is live on exit from B and is assigned a value in
B, then we ass 2 units of saving
Flow graph of an inner loop
Code sequence using global register
assignment
Register allocation by Graph coloring
• Two passes are used
– Target-machine instructions are selected as though
there are an infinite number of symbolic registers
– Assign physical registers to symbolic ones
• Create a register-interference graph
• Nodes are symbolic registers and edges connects two
nodes if one is live at a point where the other is defined.
• For example in the previous example an edge connects a
and d in the graph
• Use a graph coloring algorithm to assign registers.

You might also like