0% found this document useful (0 votes)
101 views9 pages

CD Unit 5

The document discusses several key issues in code generation: 1. The input to the code generator is intermediate code from the front end along with symbol table information. 2. The target program output can be absolute machine language, relocatable machine language, or assembly language. Efficient register allocation and instruction selection are important for performance. 3. Challenges include register allocation, instruction selection, evaluation order, and generating correct efficient code while allowing the code generator to be easily implemented, tested, and maintained. Various algorithms and approaches are discussed to address these challenges.

Uploaded by

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

CD Unit 5

The document discusses several key issues in code generation: 1. The input to the code generator is intermediate code from the front end along with symbol table information. 2. The target program output can be absolute machine language, relocatable machine language, or assembly language. Efficient register allocation and instruction selection are important for performance. 3. Challenges include register allocation, instruction selection, evaluation order, and generating correct efficient code while allowing the code generator to be easily implemented, tested, and maintained. Various algorithms and approaches are discussed to address these challenges.

Uploaded by

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

1.

Issues in the design of a code generator


Code generator converts the intermediate representation of source code into a form that can
be readily executed by the machine. A code generator is expected to generate a correct code.
Designing of code generator should be done in such a way so that it can be easily
implemented, tested and maintained.

The following issue arises during the code generation phase:

1. Input to code generator –


The input to code generator is the intermediate code generated by the front end, along
with information in the symbol table that determines the run-time addresses of the
data-objects denoted by the names in the intermediate representation. Intermediate
codes may be represented mostly in quadruples, triples, indirect triples, Postfix
notation, syntax trees, DAG’s etc. Assume that they are free from all of syntactic and
state semantic errors, the necessary type checking has taken place and the type-
conversion operators have been inserted wherever necessary.
2. Target program –
Target program is the output of the code generator. The output may be absolute
machine language, relocatable machine language, assembly language.
o Absolute machine language as an output has advantages that it can be placed
in a fixed memory location and can be immediately executed.
o Relocatable machine language as an output allows subprograms and
subroutines to be compiled separately. Relocatable object modules can be
linked together and loaded by linking loader.
o Assembly language as an output makes the code generation easier. We can
generate symbolic instructions and use macro-facilities of assembler in
generating code.
3. Instruction selection:-
Selecting best instructions will improve the efficiency of the program. It includes the
instructions that should be complete and uniform. Instruction speeds and machine
idioms also plays a major role when efficiency is considered. But if we do not care
about the efficiency of the target program then instruction selection is straight-
forward.

For example, the respective three-address statements would be translated into latter
code sequence as shown below:

P: =Q+R
S: =P+T

MOV Q, R0
ADD R, R0
MOV R0, P
MOV P, R0
ADD T, R0
MOV R0, S

Here the fourth statement is redundant as the value of the P is loaded again in that
statement that just has been stored in the previous statement. It leads to an inefficient
code sequence. A given intermediate representation can be translated into many code
sequences, with significant cost differences between the different implementations. A
prior knowledge of instruction cost is needed in order to design good sequences, but
accurate cost information is difficult to predict.

4. Register allocation issues –


Use of registers make the computations faster in comparison to that of memory, so
efficient utilization of registers is important. The use of registers are subdivided into
two subproblems:

1. During Register allocation – we select only those set of variables that will
reside in the registers at each point in the program.
2. During a subsequent Register assignment phase, the specific register is
picked to access the variable.

5. Evaluation order –
The code generator decides the order in which the instruction will be executed. The
order of computations affects the efficiency of the target code.

6.Approaches to code generation issues: Code generator must always generate the
correct code. It is essential because of the number of special cases that a code generator
might face. Some of the design goals of code generator are:

o Correct
o Easily maintainable
o Testable
o Maintainable
Code Generation Algorithm

An essential part of the algorithm is a function getReg( ). Function getReg has


access to the register and address descriptors for all the variables of the basic
block. Code generator uses getReg function to determine the available registers.

The getReg Function works as follows:

Consider an instruction of the form x: = y op z

 If variable y is already in a register R, it uses that register.


 Otherwise return an empty register R if there is one

Generate the code using code generation algorithm

d := (a - b) + (a - c) + (a - c)
Three address Target code Register ddress
code sequence descriptor descriptor

empty

t 1 := a - b R1 contains a t 1 is in R2

R2 contains t1

t 2:= a - c R3 contains c,
R1 contains t 2 t 2 is in R1

t 3 := t 1 + t 2 ADD R3, R2,R1 R3 contains t3 t 3 is in R3

t 4:= t 3 + t 2 ADD R1, R3,R1 R1 contains t 4

d:=t4 ST d,R1 R0 contains d d is in R0

Register descriptor keeps track of what is currently in each


register.

Address descriptor keeps track of the locations where the


current value of the name can be found at runtime.
REGISTER ALLOCATION AND ASSIGNMENT:-
Instructions involving only register operands are faster than
those involving memory operands. For example, assign base
addresses to one group of registers, arithmetic computations to
another, the top of the stack to a fixed register, and so on. This
approach has the advantage that it simplifies the design of a code
generator. Its disadvantage is that, applied too strictly, it uses
registers inefficiently; certain registers may go unused over
substantial portions of code, while unnecessary loads and stores
are generated into the other registers. Nevertheless, it is
reasonable in most computing environments to reserve a few
registers for base registers, stack pointers, and allow the
remaining registers to be used by the code generator as it sees fit.
The various techniques for register allocation are

Global Register Allocation:-


The code generation algorithm used registers to hold values
for the duration of a single basic block. However, all live variables
were stored at the end of each block. To save some of these stores
and corresponding loads, we might arrange to assign registers to
frequently used variables and keep these registers consistent
across block boundaries (globally). Since programs spend most of
their time in inner loops, a natural approach to global register
assignment is to try to keep a frequently used value in a fixed
register throughout a loop. One strategy for global register
allocation is to assign some fixed number of registers to hold the
most active values in each inner loop. The selected values may be
different in different loops. Registers not already allocated may be
used to hold values local to one block as in Section. This
approach has the drawback that the fixed number of registers is
not always the right number to make available for global register
allocation.
Usage Counts:-
In this technique we consider the savings obtained by keeping
a variable x in a register for the duration of a loop L. However, if
we use the approach in to generate code for a block, there is a
good chance that after x has been computed in a block it will
remain in a register if there are subsequent uses of x in that
block. Thus we count a savings of one for each use of x in loop L
by using the

∑ use(x, B) + 2 * live(x, B)

B in L

where use(x, B) is the number of times x is used in B prior to


definition of x in the same block. live(x, B) is 1 if x is live on exit
from B and is assigned a value in B, and live(x, B) is 0 otherwise.
The variables whose usage count is more registers are
allocated to them. Example as follows

Register Allocation for outer loops:-


Having assigned registers and generated code for inner loops, we
may apply the same idea to progressively larger enclosing loops.

If an outer loop L1 contains an inner loop L2 the register


allocation is as follows. If the variable x has allocated register in
L2 need not be allocated registers in L1 - L2. If we allocate x a
register in L2 but not L1, we must load x on entrance to L2 and
store x on exit from L2.

Register Allocation by Graph Coloring:-


When a register is needed for a computation but all available
registers are in use, the contents of one of the used registers
must be stored (spilled) into a memory location in order to free up
a register. Graph coloring is a simple, systematic technique for
allocating registers and managing register spills.

In the method, two passes are used. In the first, target-machine


instructions are selected as though there are an infinite number
of symbolic registers. Once the instructions have been selected, a
second pass assigns physical registers to symbolic ones. The goal
is to find an assignment that minimizes the cost of spills. In the
second pass, a register-interference graph is constructed. In RIG
there is a node for each temporary and there is an edge between
any two temporaries if they are live simultaneously at some point
in the program. Two temporaries can be allocated to the same
register if there is no edge connecting them
b and c cannot be in the same register but b and d can be in
the same register. A coloring of a graph is an assignment of
colors to nodes, such that nodes connected by an edge have
different colors. Pick a node t with fewer than k neighbors in RIG.
Eliminate t and its edges from RIG. If the resulting graph
has a k-coloring then so does the original graph.

1.Start with the RIG and with k = 4. Initially stack is empty. S= {}

2. Remove a and then d as they have less than four


neighbours.

3. Now the stack contains S= {a, d} and the modified RIG is as


follows

4. Now all the nodes have less than four neighbours. So


remove all of them and add to the stack. Thus S= { f, e, c, b, d, a}
.

5. Start assigning colors to: f, e, c, b, d, a. As k=4 the graph


can be coloured with manimum of 4 colours. Start assignging a
colour to a node by checking the adjacent coloured nodes. Repeat
the process until all the nodes are coloured.

You might also like