0% found this document useful (0 votes)
19 views20 pages

Cdunit 6

Uploaded by

Kasarap Soumya
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
19 views20 pages

Cdunit 6

Uploaded by

Kasarap Soumya
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 20

UNIT- VI

Data flow Analysis:


Data flow graphs
Data flow graph Analysis
Live variable analysis.
Code generation:
Machine dependent code generation
Object code forms
Register allocation
Generic code generation algorithm
DAG for register allocation.
Introduction to Data-Flow Analysis

• Data flow analysis refers to a body of techniques that derive information

about the flow of data along program execution paths


- Global common subexpression elimination
- Elimination of unused assignment statements
Data Flow Abstraction

• Execution of program can be viewed as series of transformations of


the program state
• Each statement execution transforms an input state to output state
• Input state is associated with the program point before statement
• output state is associated with the program point after statement
Flow Graphs and Execution Paths

• Within one basic block, the program point after a statement is the same

as the program point before the next statement


• If there is an edge from block B1 to block B2, then the program point
after the last statement of B1 may be followed immediately by the
program point before the first statement of B2.
• The execution path from point p1 to point pn is the sequence of
statements p1,p2……….pn such that for each I = 1,2, … n-1, either
• pi is the point immediately preceding a statement and pi+1 is the
point immediately following that same statement, or
• pi is the end of some block and pi+1 is the beginning of a successor
block.
The above program describes an unbounded no.of execution paths:
• (1,2,3,4,9) --- Not entering loop
• (1,2,3,4,5,6,7,8,3,4,9) -- One iteration loop
•Different information can be abstracted form program states
• Debugging with reaching definitions
• Constant Folding
Data-Flow Analysis Schema

• Data-flow value: at every program point


• Domain: The set of possible data-flow values for this application
• IN[S] and OUT[S]: the data-flow values before and after each statement s
• Data-flow problem: find a solution to a set of constraints on the IN [s] ‘s
and OUT[s] ‘s, for all statements s.
– based on the semantics of the statements ("transfer functions" )

– based on the flow of control.

• Transfer function: relationship between the data-flow values before and


after a statement.

– Forward: OUT[s] = fs(IN[s])

– Backward: IN[s] = fs(OUT[s])

• Within a basic block (s1,s2,…,sn)

– IN[s +1 ] = OUT[s ], for all i = 1, 2, ..., n-1


Data-Flow Schemas on Basic Blocks

• Each basic block B (s1,s2,…,sn) has

– IN – data-flow values immediately before a block

– OUT – data-flow values immediately after a block

– IN[B] = IN[S1]

– OUT[B] = OUT[Sn]

– OUT[B] = fB (IN[B] )

• Where fB = fsn ◦Between


••• ◦ fs2 ◦ fs
Blocks
1

• Forward analysis (eg: Reaching definitions)

– IN[B] = UP a predecessor of B OUT[P]

• Backward analysis (eg: live variables)

– IN[B] = fB (OUT[B])

– OUT[B] = US a successor of B IN[S].


Reaching Definition
• A definition d reaches a point p
– if there is a path from the point immediately following d to p and
– d is not killed along the path (i.e. there is no redefinition of the same
variable in the path)
• A definition of a variable is killed between two points when there is
another definition of that variable along the path.

Formalizing Reaching Definitions

• Each basic block has


– IN - set of definitions that reach beginning of block

– OUT - set of definitions that reach end of block

– GEN - set of definitions generated in block

– KILL - set of definitions killed in block

• Compiler scans each basic block to derive GEN and KILL sets
The Reaching definitions are defined by the following equations:
A Simple Code Generator

• One of the primary issues: deciding how to use registers to best


advantage
• Four principal uses:
– In most machine architectures, some or all of the operands of
an operation must be in registers in order to perform the
operation.
– Registers make good temporaries to hold the result of a sub
expression or a variable that is used only within a single basic
block.
– Registers are used to hold (global) values that are computed in
one basic block and used in other blocks.
– Registers are often used to help with run-time storage
management.

10
A Simple Code Generator

• Assumption of the code-generation algorithm in this section:


– Some set of registers is available to hold the values that are
used within the block.
– The basic block has already been transformed into a preferred
sequence of three-address instructions
– For each operator, there is exactly one machine instruction that
takes the necessary operands in registers and performs that
operation, leaving the result in a register

11
Register and Address Descriptors

• Descriptors are necessary for variable load and store decision.


• Register descriptor
– For each available register

– Keeping track of the variable names whose current value is in


that register
– Initially, all register descriptors are empty

• Address descriptor
– For each program variable

– Keeping track of the location (s) where the current value of


that variable can be found
– Stored in the symbol-table entry for that variable name.

12
The Code-Generation Algorithm
• Function getReg(I)
– Selecting registers for each memory location associated with the
three-address instruction I.
• Machine Instructions for Operations
– For a three-address instruction such as x = y + z, do the following:

1. Use getReg(x = y + z) to select registers for x, y, and z. Call these Rx,


Ry, and Rz .

2 . If y is not in Ry (according to the register descriptor for Ry) , then


issue an instruction

LD Ry , y' , where y' is one of the memory locations for y (according


to the address descriptor for y) .

3. Similarly, if z is not in Rz , issue an instruction LD Rz, z’ , where z’ is a


location for z.
13
4. Issue the instruction ADD Rx , Ry , Rz.
The Code-Generation Algorithm

• Machine Instructions for Copy Statements


– For x=y, getReg will always choose the same register for both x and y.

– If y is not in the register Ry , generate instruction LD Ry , y.

– If y was in Ry , do nothing.

– Need to adjust the register description for Ry so that it includes x as


one of the values.

• Ending the Basic Block


– generate the instruction ST x, R, where R is a register in which x's
value exists at the end of the block if x is live on exit from the block.

14
The Code-Generation Algorithm
• Managing Register and Address Descriptors
1 . For the instruction LD R, x
– (a) Change the register descriptor for register R so it holds only x.
– (b) Change the address descriptor for x by adding register R as an
additional location.
2. For the instruction ST x, R, change the address descriptor for x to
include its own location.
3. For an operation such as ADD Rx , Ry , Rz for x = y + z
– (a) Change the register descriptor for Rx so that it holds only x.
– (b) Change the address descriptor for x so that its only location is Rx .
– Note that the memory location for x is not now in the address
descriptor for x .
– (c) Remove Rx from the address descriptor of any variable other than
x.
4. When process a copy statement x = y , after generating the load for y
into register Ry, if needed, and after managing descriptors as for all
load statements (per rule 1 ) :
– (a) Add x to the register descriptor for Ry .
– (b) Change the address descriptor for x so that its only location is Ry .
15
16
Design of the Function getReg

• Pick a register Ry for y in x=y+z


– 1 . y is currently in a register, pick the register.
– 2. y is not in a register, but there is an empty register, pick the register.
– 3. y is not in a register, and there is no empty register.
• Let R be a candidate register, and suppose v is one of the variables in
the register descriptor
• need to make sure that v's value either is not needed, or that there is
somewhere else we can go to get the value of R.
(a) OK if the address descriptor for v says that v is somewhere besides R,
(b) OK if v is x, and x is not one of the other operands of the instruction(z
in this example)
(c) OK if v is not used later
(d) Generate the store instruction ST v, R to place a copy of v in its own
memory location.
17
This operation is called a spill.
Design of the Function getReg

• Pick a register Rx for x in x=y+z


– Almost as for y, differences:

1. Since a new value of x is being computed, a register that holds only x


is a choice for Rx;

2. If y is not used after the instruction, and Ry holds only y after being
loaded, then Ry can be used as Rx; A similar option holds regarding z
and Rz ·
Exercise: Generate the machine code for the following Expressions
(a) x = a/(b+c) – d * (e + f)
(b) I = 0;
while( I < 10)
{
a[I] = 0
I = I + 1;
18
}
Assignment - 6

1. Take a sample flow graph and explain how the functions gen and kill are
computed. Also compute IN and OUT set for each block using Iteration
algorithm to compute reaching definitions.
2. Generate the code for the following block
I = 0; while(I < 10) { a[I] = 0; I = I + 1; }
3. Explain the following terms.
(a) Register Descriptor (b) Address Descriptor (c) Instruction costs
4. Explain in detail about simple code generation algorithm with example.
5. Explain about live variable analysis with example.

You might also like