You are on page 1of 21

UNIT IV:

Run Time Environments: Storage Organization, Run Time Storage Allocation,


Activation Records, Procedure Calls, Displays,
Code Optimization: The Principle Sources of Optimization, Basic Blocks,
Optimization of Basic Blocks, Structure Preserving Transformations, Flow
Graphs, Loop Optimization, Data-Flow Analysis, Peephole Optimization

Runtime Environments

The program consists of names for procedures, identifiers etc., that require
mapping with the actual memory location at runtime.
Runtime environment is a state of the target machine, which may include
software libraries, environment variables, etc., to provide services to the
processes running in the system.

1.Storage organization
Runtime storage can be subdivided to hold :

STORAGE ALLOCATION TECHNIQUES

i. Static Storage Allocation

● For any program if we create memory at compile time, memory will be


created in the static area.
● For any program if we create memory at compile time only, memory is
created only once.
● It don’t support dynamic data structure i.e memory is created at compile
time and deallocated after program completion.
1
● The drawback with static storage allocation is recursion is not supported.

● Another drawback is size of data should be known at compile time.

Eg- FORTRAN was designed to permit static storage allocation.

ii. Stack Storage Allocation

● Storage is organized as a stack and activation records are pushed and


popped as activation of function begins and end respectively. Locals are
contained in activation records so they are bound to fresh storage in each
activation.

● Recursion is supported in stack allocation

iii. Heap Storage Allocation

● Memory allocation and deallocation can be done at any time and at any
place depending on the requirement of the user.

● Heap allocation is used to dynamically allocate memory to the variables and


claim it back when the variables are no more required. Recursion is
supported.

Activation record
● Stack is used for managing procedure calls
● Storage is organized as a stack and a new activation record is pushed on
the stack whenever a function is called and popped when the function
call ends .
● The information needed during an execution of a procedure is kept on a
block of storage called activation record.
● Locals are contained in activation records so they are bound to fresh
storage in each activation.

● Recursion is supported in stack allocation. Stack grows with each call


and shrinks with each procedure return/terminate

2
Fig: Activation Record
local data: field for local data.
saved machine status: holds information about machine status before
procedure call.
access link or static link : to access non local data.
control link or dynamic link :points to activation record of caller.
actual parameters: field to hold actual parameters.
returned value: field for holding value to be returned.

Fig: Stack of Activation Records

3
Procedure Calls

Calling Sequences

Procedure calls are implemented by calling sequences, which consists of code


that allocates an activation record on the stack and enters information into its
fields.

A return sequence is similar code to restore the state of the machine so the
calling procedure can continue its execution after the call.

Call Sequence
Caller evaluates the actual parameters
Caller stores return address and other values (control link) into callee’s
activation record
Callee saves register values and other status information
Callee initializes its local data and begins execution.
Return Sequence
• Callee places a return value next to activation record of caller
• Restores registers using information in status field
• Branch to return address
• Caller copies return value into its own activation record

4
Displays

● Static links are stored in a single array called a display


● If access links are used in the search, then the search can be slow if
nesting depth is high

· Faster access to non locals

· Uses an array of pointers to activation records.

· Non locals at depth i is in the activation record pointed to by d[i]

Fig: display

Assume that procedures q, e is nested inside procedure s and procedure


p is nested inside procedure q. Nesting depth of s is 1 and q and e is 2.
Nesting depth of p is 3.

● A nonlocal X is found in the following manner:

● Use one array access to find the activation record containing X. if the
most-closely nested declaration of X is at nesting depth I, the d[i] points
to the activation record containing the location for X

BASIC BLOCKS
• A basic block is a sequence of consecutive statements in which control
enters at the beginning and leaves at the end without halt or possibility of
branching except at the end.

5
Optimization of basic blocks
4.1 DAG representation of Basic Block:-

A DAG representation of a basic block is a directed acyclic graph in which


the nodes of the DAG represent the statements within the block and each
child of a node corresponds to the statement that is the last definition of
an operand used in the statement. Many important techniques for local
optimization begin by transforming a basic block into a DAG (directed
acyclic graph).

We construct a DAG for basic block as follows:


1. There is a node in the DAG for each of the initial values of the
variables appearing in basicblock.
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 no desare designated output nodes. These are the nodes
whose variables live on exit from the block; that is, their values may be
used later,in another block of the flow graph.

6
Algorithm for Construction of DAG - for x := y op z.

• If node(y) is undefined, create a leaf labeled y and let node(y) be this leaf. If
node(z) is undefined, create a leaf labeled z and let node(z) be that leaf
• Determine if there is a node labeled op, whose left child is node(y) and its
right child is node(z). If not, create such a node. Let n be the node found or
created.

-Leaves labeled by unique identifiers


• Interior nodes labeled by operator symbols
• Nodes optionally given a sequence of identifiers, having the value
represented by the nodes

• We start the construct of DAG form the first statement a = b + c. Since b


and c are defined elsewhere and used in this block they are designated as b0
and c0. For the expression a = b + c operator + becomes the root and b0 and c0
become the left and right child respectively.

Applications of DAG:

7
4.2 Finding local common sub expressions

8
The Use of algebraic identities

Fl
ow Graphs
• Once an intermediate-code program is partitioned into basic blocks, we
represent the flow of control between them by a flow graph.
• The nodes of the flow graph are the basic blocks
• There is an edge from B1 to B2iff B2 immediately follows B1 in some execution
sequence
– B2 immediately follows B1 in program text
• B1 is a predecessor of B2, B2 is a successor of B1

The dot product between two arrays is the sum of products

Consider two arrays

X={ 1,2,3},Y= {4,5,6}

The dot product of two arrays = 1*4 + 2*5 + 3*6 = 4+10+18 = 32

Generate the flow graph for the following program for finding dot product of
two arrays x and y of length 20
prod = 0;
i = 1;
do
{
prod = prod + a[i] * b[i];
i=i+1;
}while ( i<=20 );

9
Flow graph can be constructed by first converting program into three
address code

Partitioning three-address instructions into basic blocks:- First, we determine


those instructions in the intermediate code that are leaders, that is, the first
instructions in the basic block. The rules for finding leaders are:
1. The first three-address instruction in the intermediate code is a leader.
2. Any instruction that is the target of a conditional or unconditional jump is a
leader.
3.Any instruction that immediately follows a conditional or unconditional jump
is a leader.
Then, for each leader, its basic block consists of itself and all instructions up to
but not including the next leader or the end of the intermediate program.

10
Data Flow Analysis
● Data-flow analysis is a technique for gathering information about the
possible set of values calculated at various points in a computer
program. A program's control flow graph (CFG) is used to determine
those parts of a program to which a particular value assigned to a
variable might propagate.

Basic Terminologies –

● Definition Point: a point in a program containing some definition.


● Reference Point: a point in a program containing a reference to a data item.
● Evaluation Point: a point in a program containing evaluation of expression

The Data Flow Abstraction

11
7.2 Data Flow Analysis Schema

A DFA schema consists of

● A control-flow graph

● A direction of data-flow (forward or backward)

● A set of data-flow values

● A confluence operator (normally set union or intersection)

● Transfer functions for each block

Data Flow Analysis Schemas (or) Data Flow Properties –


i) Reaching Definitions ii) Live Variable Analysis
iii) Available Expressions iv) Busy Expressions

7.2.1 Reaching Definition

– A definition D is reaches a point P if there is path from D to P in which D is


not killed, i.e., not redefined.
Advantage –
It is used in constant and variable propagation.
Example 1 –

12
IN[B] and OUT[B] = input and output of basic block B
Transfer function for block B i.e Out[B] = Gen[B] U (in[B]-Kill[B]
Meet operation (U):
IN[B] = out[P1 ] U out[P2 ] U ... U out[Pn ], where p1 , ..., pn are all the
predecessors of B
GEN[B] = Set of definition generated from basic block B
KILL[B] =set of definitions killed by defs in B
IN[Entry] = φ, OUT[Entry] = φ,

13
7.2.2 Live Variable Analysis
. A variable v is live at point p if
– the value of v is used along some path in the flow graph starting at p.

Fig: Example1

14
OUT[
B] = IN[S1 ] U IN[S2 ] U ... U IN[Sn ], where s1 , ..., sn are all successors of B

Advantage –
1. Live Variable analysis is useful for register allocation.
2. It is used in dead code elimination.

7.2.3 Available Expressions

An expression x + y is available at a point p, if every path from the entry node


to p evaluates x + y, and after the last such evaluation, prior to reaching p,
there are no subsequent assignments to x or y.
Example1

15
Available Expression Computation Example 2

Fig: Common sub expressions across blocks

- 4 ∗ i is a Common Sub Exp in B3, if it is available at the entry point of


B3 i.e., if i is not assigned a new value in B2 or 4 ∗ i is recomputed after
i is assigned a new value in B2.
- In the above diagram, variable i is not assigned a new value.
- Useful for global common sub-expression elimination

Data Flow Equations for Available Expressions

16
7.2.4 Busy Expressions
An expression E is very busy at Point P if no matter what path is taken from P,
the expression E is evaluated before any of its operands are defined.
Example: An expression a+b is very busy at a point P if a+b is evaluated on all paths from P to
EXIT and there is no definition of a or b on a path between P and an evaluation of a+b

PEEPHOLE OPTIMIZATION
Peephole is machine dependent optimization. Peephole optimization is a type of Code
Optimization performed on a small part of the code. It is performed on a very small set of
instructions in a segment of code.

A simple but effective technique for improving the target code is peephole optimization,
a method for trying to improve the performance of the target program by examining a short
sequence of target instructions (called the peephole) and replacing these instructions by a shorter
or faster sequence, whenever possible.

The peephole is a small, moving window on the target program. The code in the peephole
need not be contiguous, although some implementations do require this. It is characteristic of
peephole optimization that each improvement may spawn opportunities for additional
improvements.

Characteristics of peephole optimizations:

17
→Redundant-instructions elimination
→Flow-of-control optimizations
→Algebraic simplifications
→Use of machine idioms
→Unreachable

Redundant Loads And Stores:

If we see the instructions sequence


(1) MOV R0,a
(2) MOV a,R0

we can delete instructions (2) because whenever (2) is executed. (1) will ensure that the
value of a is already in register R0.If (2) had a label we could not be sure that (1) was always
executed immediately before (2) and so we could not remove (2).

Unreachable Code:

Another opportunity for peephole optimizations is the removal of unreachable


instructions. An unlabeled instruction immediately following an unconditional jump may be
removed. This operation can be repeated to eliminate a sequence of instructions. For example,
for debugging purposes, a large program may have within it certain segments that are executed
only if a variable debug is 1. In C, the source code might look like:

#define debug 0
….

If ( debug ) {
Print debugging information }
In the intermediate representations the if-statement may be translated as:

If debug =1 goto L1 goto L2

L1: print debugging information L2: ………………………… (a)

One obvious peephole optimization is to eliminate jumps over jumps .Thus no matter what
the value of debug; (a) can be replaced by:

18
If debug ≠1 goto L2
Print debugging information
L2: …………………………… (b)

If debug ≠0 goto L2
Print debugging information
L2: …………………………… (c)

As the argument of the statement of (c) evaluates to a constant true it can be replaced
By goto L2. Then all the statements that print debugging aids are manifestly unreachable
and can be eliminated one at a time.

Flows-Of-Control Optimizations:

The unnecessary jumps can be eliminated in either the intermediate code or the target
code by the following types of peephole optimizations. We can replace the jump sequence
goto L1
….

L1: gotoL2 (d)

by the sequence
goto L2
….
L1: goto L2
If there are now no jumps to L1, then it may be possible to eliminate the statement L1:goto
L2 provided it is preceded by an unconditional jump .Similarly, the sequence

if a < b goto L1
….

L1: goto L2 (e)

can be replaced by
If a < b goto L2
….
L1: goto L2

19
Finally, suppose there is only one jump to L1 and L1 is preceded by an unconditional
goto. Then the sequence
goto L1
L1: if a < b goto L2 (f) L3:

may be replaced by
If a < b goto L2
goto L3
…….

L3:

While the number of instructions in(e) and (f) is the same, we sometimes skip the
unconditional jump in (f), but never in (e).Thus (f) is superior to (e) in execution time.

Algebraic Simplification:

There is no end to the amount of algebraic simplification that can be attempted through
peephole optimization. Only a few algebraic identities occur frequently enough that it is worth
considering implementing them. For example, statements such as
x := x+0 or
x := x * 1

are often produced by straightforward intermediate code-generation algorithms, and they can be
eliminated easily through peephole optimization.

Reduction in Strength:

Reduction in strength replaces expensive operations by equivalent cheaper ones on the


target machine. Certain machine instructions are considerably cheaper than others and can often
be used as special cases of more expensive operators.

For example, x² is invariably cheaper to implement as x*x than as a call to an


exponentiation routine. Fixed-point multiplication or division by a power of two is cheaper to
implement as a shift. Floating-point division by a constant can be implemented as multiplication
by a constant, which may be cheaper.

20
2
X → X*X

Use of Machine Idioms:

The target machine may have hardware instructions to implement certain specific
operations efficiently. For example, some machines have auto-increment and auto-decrement
addressing modes. These add or subtract one from an operand before or after using its value. The
use of these modes greatly improves the quality of code when pushing or popping a stack, as in
parameter passing. These modes can also be used in code for statements like i : =i+1.
i:=i+1 → i++
i:=i-1 → i- -

21

You might also like