0% found this document useful (0 votes)
25 views32 pages

Print CC

Compiler construction

Uploaded by

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

Print CC

Compiler construction

Uploaded by

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

outline

• the translation of languages guided by context-free


grammars.
Chapter 5 • A syntax-directed definition specifies the values of
Syntax-Directed attributes by associating semantic rules with the
grammar productions.
Translation We associate information with a language construct
by attaching attributes to the grammar symbol(s)
representing the construct,

outline outline
• a syntax-directed translation scheme embeds • The most general approach to syntax-
program fragments called semantic actions directed translation is to construct a parse
within production bodies.
tree or a syntax tree, and then to compute
E → El +T { print ' + ' }
the values of attributes at the nodes of the
The position of a semantic action in a production tree by visiting the nodes of the tree.
body determines the order in which the action is
executed. • a class of syntax-directed translations called
in general, semantic actions may occur at any "L-attributed translations "
position in a production body. • a smaller class, called "S-attributed
translations" (S for synthesized )

5.1 Syntax-Directed Definitions 5.1.1 Inherited and Synthesized Attributes

• A syntax-directed definition (SDD) is a context-free • A synthesized attribute: for a nonterminal A


grammar together with attributes and rules. at a parse-tree node N is defined by a semantic
• Attributes are associated with grammar symbols and rule associated with the production at N.
rules are associated with productions.
the production must have A as its head. A
• X.a : denote the value of a at a particular parse-tree
synthesized attribute at node N is defined only
node labeled X.
in terms of attribute values at the children of
• Attributes may be of any kind: numbers, types, table
references, or strings, for instance. N and at N itself.
5.1.1 Inherited and Synthesized Attributes 5.1.1 Inherited and Synthesized Attributes
• we do not allow an inherited attribute at node N to
• An inherited attribute for a nonterminal B at
be defined in terms of attribute values at the
a parse-tree node N is defined by a semantic children of node N.
rule associated with the production at the
• we do allow a synthesized attribute at node N to
parent of N. be defined in terms of inherited attribute values at
Note that the production must have B as a node N itself.
symbol in its body. An inherited attribute at • Terminals can have synthesized attributes, but not
node N is defined only in terms of attribute inherited attributes. Attributes for terminals have
values at N's parent, N itself, and N's lexical values that are supplied by the lexical
siblings. analyzer;

5.1.1 Inherited and Synthesized Attributes 5.1.1 Inherited and Synthesized Attributes
• PRODUCTION •SEMANTIC RULES
1) L → E n L.val = E.val • An S-attributed SDD can be implemented naturally in
2) E → E l + T E.val=E1.val+T.val conjunction with an LR parser.
3) E → T E.val = T.val • An SDD without side effects is sometimes called an
4) T → Tl * F T.val=Tl.val  F.val attribute grammar.
5) T → F T.val = F.val
• The rules in an attribute grammar define the value of an
6) F → ( E ) F.val = E.val attribute purely in terms of the values of other attributes
7) F → digit F. val = digit .lexval and constants.
S-attributed: An SDD that involves only synthesized
attributes is called S-attributed .

5.1.2 Evaluating an SDD at the Nodes 5.1.2 Evaluating an SDD at the


of a Parse Tree Nodes of a Parse Tree
• To visualize the translation specified by an
• How do we construct an annotated parse
SDD, it helps to work with parse trees, even
tree?
though a translator need not actually build a
parse tree. • In what order do we evaluate attributes?
• annotated parse tree : A parse tree showing Before we can evaluate an attribute at a
the value(s) of its attribute(s). node of a parse tree, we must evaluate all
the attributes upon which its value depends.
5.1.2 Evaluating an SDD at the 5.1.2 Evaluating an SDD at the
Nodes of a Parse Tree Nodes of a Parse Tree
• we can evaluate synthesized attributes in any bottom- • Example 5.2
up order.
• For SDD's with both inherited and synthesized
attributes, there is no guarantee that there is even one
order in which to evaluate attributes at nodes.

These rules are circular; it is impossible to


evaluate either A.s at a node N or B.i at the
child of N without first evaluating the other.
Figure 5.3: Annotated parse tree for 3 * 5 + 4 n

5.1.2 Evaluating an SDD at the 5.1.2 Evaluating an SDD at the


Nodes of a Parse Tree Nodes of a Parse Tree
• Inherited attributes are useful when the structure of a • Example 5.3 Each of the nonterminals T
parse tree does not "match" the abstract syntax of the and F has a synthesized
source code. attribute val.
the left operand 3 appears The terminal digit has a
in a different subtree of synthesized attribute lexval.
the parse tree from *.
The nonterminal T' has two
An inherited attribute will attributes: an inherited
therefore be used to pass attribute inh and a synthesized
the operand to the attribute syn.
operator.
Figure 5.5: Annotated parse tree for 3 * 5

5.2 Evaluation Orders for SDD's 5.2.1 Dependency Graphs


• A dependency graph depicts the flow of
• "Dependency graphs" are a useful tool for
determining an evaluation order for the attribute
information among the attribute instances in
instances in a given parse tree. a particular parse tree.
• Edges express constraints implied by the
two important classes of SDD's:
semantic rules.
the "S-attributed"
the more general "L-attributed " SDD's.
5.2.1 Dependency Graphs 5.2.1 Dependency Graphs
• The dependency graph has a node for each attribute
• Example 5.4
associated with X .
• Suppose that a semantic rule associated with a
production p defines the value of synthesized
attribute A.b in terms of the value of X.c . Then, the
dependency graph has an edge from X.c to A.b.
• Suppose that a semantic rule associated with a
production p defines the value of inherited attribute
B.c in terms of the value of X.a. Then, the
dependency graph has an edge from X.a to B.c.
Figure 5.6: E. val is synthesized from El. val and E2. val

5.2.1 Dependency Graphs 5.2.2 Ordering the Evaluation of Attributes


• the only allowable orders of evaluation are those
• Example 5.5 sequences of nodes Nl, N2,. . . , Nk such that if there is
an edge of the dependency graph from Ni to Nj; then i
< j.
• Such an ordering embeds a directed graph into a linear
order, and is called a topological sort of the graph.
•If there is any cycle in the graph, then there are no
topological sorts; that is,there is no way to evaluate the
SDD on this parse tree.
•If there are no cycles,however, then there is always at
Figure 5.7: Dependency graph for the annotated parse tree of Fig. 5.5
least one topological sort.

5.2.3 S-Attributed Definitions 5.2.3 S-Attributed Definitions


• An SDD is S-attributed if every attribute is
postorder (N) {
synthesized.
for ( each child C of N, from the left ) postorder(C);
Example 5.7 : The SDD of Fig. 5.1 is an example of evaluate the attributes associated with node N;
an S-attributed definition. Each attribute, L.val, E.va1, }
T.val, and F.val is synthesized.

•When an SDD is S-attributed, we can evaluate its S-attributed definitions can be implemented during
attributes in any bottom up order of the nodes of the bottom-up parsing, since a bottom-up parse
parse tree. (performing a postorder traversal of the parse corresponds to a postorder traversal.
tree)
5.2.4 L-Attributed Definitions 5.2.4 L-Attributed Definitions
each attribute must be either
• Synthesized, or
• Inherited, but with the rules limited as follows.
• between the attributes associated with a Suppose that there is a production A → X 1X2 …… Xn,
production body, dependency-graph edges can and that there is an inherited attribute Xi.a computed
go from left to right, but not from right to left by a rule associated with this production.
(hence "L-attributed"). (1) Inherited attributes associated with the head A.
(2) Either inherited or synthesized attributes associated
with the occurrences of symbols X1, X2,. . . , Xi-1
located to the left of Xi.
(3) Inherited or synthesized attributes associated with this
occurrence of Xi itself, but only in such a way that
there are no cycles in a dependency graph formed by
the attributes of this Xi.

5.2.4 L-Attributed Definitions 5.2.5 Semantic Rules with Controlled Side


Effects
• Example 5.8 : The SDD in Fig. 5.4 is L-attributed.
• we strike a balance between attribute grammars and
translation schemes.
• Attribute grammars have no side effects and allow any
evaluation order consistent with the dependency graph.
Example 5.9 : Any SDD containing the following
production and rules cannot be L-attributed: • Translation schemes impose left-to-right evaluation and
allow semantic actions to contain any program fragment.

5.2.5 Semantic Rules with Controlled 5.2.5 Semantic Rules with Controlled
Side Effects Side Effects
• control side effects in SDD's in one of the • Example 5.10 : The SDD in Fig. 5.8 takes a simple
declaration D consisting of a basic type T followed by a
following ways: list L of identifiers.
• Permit incidental side effects that do not 1) D → T L L.inh = T.type
constrain attribute evaluation. 2) T → int T. type = integer
• Constrain the allowable evaluation orders, so 3) T → float T.type = float
4) L → L1 , id Ll.inh=L.inh
that the same translation is produced for any
allowable order. addType(id.entry, L.inh)
5) L → id add Type(id entry, L.inh)
5.2.5 Semantic Rules with Controlled 5.3 Applications of Syntax-Directed
Side Effects Translation
• two SDD's for constructing syntax trees for
expressions.
The first, an S-attributed definition, is suitable for
use during bottom-up parsing.
The second, L-attributed, is suitable for use
during top-down parsing.
• The final example of this section is an L-
attributed definition that deals with basic
and array types.
Figure 5.9: Dependency graph for a declaration float idl,id2,id3

5.3.1 Construction of Syntax Trees 5.3.1 Construction of Syntax Trees


• Example 5.1.1 : The S-attributed definition in Fig.
5.10 constructs syntax trees for a simple
• If the node is a leaf, an additional field holds the expression grammar involving only the binary
lexical value for the leaf. A constructor function operators +and -.
Leaf ( op, val ) creates a leaf object.
PRODUCTION SEMANTIC RULES
• If the node is an interior node, there are as many 1) E → E1 + T E.node = new Node('+', E1 .node, T.node)
additional fields as the node has children in the 2) E → E1 - T E.node = new Node('-', El .node, T.node)
syntax tree. A constructor function Node takes two 3) E → T E.node = T.node
or more arguments: Node(op, cl, c2, . . . , ck) 4) T →( E ) T.node = E.node
5) T → id T.node = new Leaf (id, id.entry)
6) T → nurn T.node = new Leaf (num, num.val)

Figure 5.10: Constructing syntax trees for simple expressions

5.3.1 Construction of Syntax Trees 5.3.1 Construction of Syntax Trees


1) pl = new Leaf(id, entry-a); • Example 5.12 : The L-attributed definition in Fig. 5.13
2) p2= new Leaf (num, 4);
3) p3 = new Node('-', pl, p2);
4) p4 = new Leaf(id, entry-c);
5) p5 = new Node('+', p3,p4);

Figure 5.12: Steps in the


construction of the syntax
tree for a - 4 + c

Figure 5.11: Syntax tree for a - 4 + c


Figure 5.13: Constructing syntax trees during top-down parsing
5.3.1 Construction of Syntax Trees 5.3.2 The Structure of a Type
• Inherited attributes are useful when the structure of
the parse tree differs from the abstract syntax of the
input; attributes can then be used to carry
information from one part of the parse tree to another.
Example 5.13: In C, the type int [2][3] can be read
as, "array of 2 arrays of 3 integers." The corresponding
type expression array(2, array(3, integer)) is
represented by the tree in Fig. 5.15
Figure 5.14: Dependency graph for a - 4 + c, with the SDD of Fig. 5.13
Figure 5.15: Type
expression for int [2] [3]

5.3.2 The Structure of a Type 5.3.2 The Structure of a Type


• PRODUCTION •SEMANTIC RULES
T → BC T.t = C.t
C.b = B.t
B → int B.t = integer
B → float B.t = float
C → [ num ] C1 C.t = array (num.val , C1 .t)
C1.b = C.b
C→ C.t = C.b

Figure 5.16: T generates either a basic type or an array type

Figure 5.17: Syntax-directed translation of array types

作业
• 5.2.2
CS 335: Runtime
• 5.2.3 (a, b, c)
Environments
• 5.3.1 Swarnendu Biswas

Semester 2019-2020-II
CSE, IIT Kanpur

Content influenced by many excellent references, see References slide for acknowledgements.
An Overview of Compilation Abstraction Spectrum
source program target program
• Translating source code requires dealing with all programming
language abstractions
lexical analyzer code generator • For example, names, procedures, objects, flow of control, and exceptions
symbol table
• Physical computer operates in terms of several primitive operations
• Arithmetic, data movement, and control jumps
syntax analyzer error handler code optimizer • It is not enough to just translate intermediate code to machine code
• For e.g., need to manage memory when a program is executing

intermediate code
semantic analyzer
generator

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas

Runtime Environment Issues Dealt with Runtime Environments


• A runtime environment is a set of data structures maintained at run • How to pass parameters when a procedure is called?
time to implement high-level structures • What happens to locals when procedures return from an activation?
• For example, stack, heap, static area, and virtual function tables
• Depends on the features of the source and the target language
• How to support recursive procedures?
• Compilers create and manage a runtime environment in which the • Can a procedure refer to nonlocal names? If yes, then how?
target programs are executed •…
• Runtime deals with the layout, allocation, and deallocation of storage
locations, linkages between procedures, and passing parameters
among other concerns

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas

Storage Organization Strategies for Storage Allocation


• Target program runs in its own logical space Code • Static allocation – Lay out storage at compile time only by studying
• Size of generated code is usually fixed at compile time the program text
Static • Memory allocated at compile time will be in the static area
• Unless code is loaded or produced dynamically
• Compiler can place the executable at fixed addresses Heap • Dynamic allocation – Storage allocation decisions are made when the
program is running
• Runtime storage can be subdivided into • Stack allocation – Manage run-time allocation with a stack storage
• Target code Free Memory
• Local data are allocated on the stack
• Static data objects such as global constants • Heap allocation – Memory allocation and deallocation can be done at any
• Stack to keep track of procedure activations and local data Stack time
• Heap to keep all other information like dynamic data • Requires memory reclamation support

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas


Static Allocation Stack vs Heap Allocation
• Names are bound to storage locations at compilation time Stack Heap
• Bindings do not change, so no run time support is required
• Names are bound to the same location on every invocation • Allocation/deallocation is • Allocation/deallocation is explicit
• Values are retained across activations of a procedure automatic
• Limitations • Less expensive • More expensive
• Size of all data objects must be known at compile time • Space for allocation is limited • Challenge is fragmentation
• Data structures cannot be created dynamically
• Recursive procedures are not allowed

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas

Static vs Dynamic Allocation


Static Dynamic

• Variable access is fast • Variable access is slow


• Addresses are known at compile • Accesses need redirection through
time stack/heap pointer
• Cannot support recursion • Supports recursion
Procedure Abstraction

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas

Procedure Calls Procedure Calls


• Procedure definition is a declaration that associates an identifier with • Creates a controlled execution environment
a statement (procedure body) • Each procedure has its own private named storage or name space
• Formal parameters appear in declaration • Executing a call instantiates the callee’s name space
• Actual parameters appear when a procedure is called
• Abstractions provided by procedures
• Important abstraction in programming • Control abstraction
• Defines critical interfaces among large parts of a software • Name space
• External interface

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas


Control Abstraction Procedure Calls
• Each language has rules to • Each execution of a procedure 𝑃 is an activation of the procedure 𝑃
• Invoke a procedure • A procedure is recursive if an activation can begin before an earlier
• Map a set of arguments from the caller’s name space to the callee’s name activation of the same procedure has ended
space
• If procedure is recursive, several activations may be alive at the same time
• Return control to the caller, and continue execution after the call
• Linkage convention standardizes the actions taken by the compiler • The lifetime of an activation of 𝑃 is all the steps to execute 𝑃
and the OS to make a procedure call including all the steps in procedures that 𝑃 calls
• Given activations of two procedures, their lifetimes are either non-
overlapping or nested

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas

Activation Tree Quicksort Code


int a[11]; void quicksort(int m, int n) {
• Depicts the way control enters and leaves int g() { return 42; }
void readArray() { int i;
activations int f() { return g(); }
int i; if (n > m) {
• Root represents the activation of main main() {
… i = partition(m, n);
g();
• Each node represents activation of a } quicksort(m, i-1);
procedure f(): quicksort(i+1, n);
• Node 𝑎 is the parent of 𝑏 if control flows } int partition(int m, int n) { } }
from 𝑎 to 𝑏 …
• Node 𝑎 is to the left of 𝑏 if lifetime of 𝑎 main } int main() {
occurs before 𝑏 readArray();
a[0] = -99999;
• Flow of control in a program corresponds g f
a[10] = 99999;
to depth-first traversal of activation tree quicksort(1, 9);
g }

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas

enter main()

Activation Tree Example of Procedure Activations enter readArray()


leave readArray()
main() Also referred to as dynamic enter quicksort(1,9)
call graph enter partition(1,9)
main()
leave partition(1,9)
enter quicksort(1,3)
rdArr() qsort(1,9)
...
rdArr() qsort(1,9)
leave quicksort(1,3)
enter quicksort(5,9)
partn (1,9) qsort(1,3) qsort(5,9)
partn (1,9) qsort(1,3) qsort(5,9) ...
leave quicksort(5,9)
leave quicksort(1,9)
partn (5,9) qsort(5,5) qsort(7,9) partn (5,9) qsort(5,5) qsort(7,9)
partn (1,3) qsort(1,0) qsort(2,3) partn (1,3) qsort(1,0) qsort(2,3) leave main()

partn (2,3) qsort(2,1) qsort(3,3) partn (7,9)qsort(7,7)qsort(9,9)


partn (2,3) qsort(2,1) qsort(3,3) partn (7,9) qsort(7,7) qsort(9,9)

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas


Control Stack Is a Stack Sufficient?

• Procedure calls and returns are usually managed by When will a control stack work?
a run-time stack called the control stack qsort(2,3)
• Once a function returns, its activation record cannot be referenced again
• Each live activation has an activation record on the
control stack qsort(1,3) • We do not need to store old nodes in the activation tree
• Stores control information and data storage needed to • Every activation record has either finished executing or is an ancestor of
manage the activation qsort(1,9)
the current activation record
• Also called a frame
main()
• Frame is pushed when activation begins and popped When will a control stack not work?
when activation ends
• Once a function returns, its activation record cannot be referenced again
• Suppose node 𝑛 is at the top of the stack, then the
stack contains the nodes along the path from 𝑛 to • Function closures – procedure and run-time context to define free
the root variables
CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas

Is a Stack Sufficient? Activation Record


When will a control stack work? • A pointer to the current activation record Actual parameters
• Once a function returns, its activation record cannot be referenced again is maintained in a register
Returned values
• We do not need to store old nodes in the activation tree • Fields in an activation record
• Every activation record has either finished executing or is an ancestor of • Temporaries – evaluation of expressions Control link

the current activation record • Local data – field for local data
Access link
• Saved machine status – information about the
When will a control stack not work? machine state before the procedure call Saved machine
status
• Return address (value of program counter)
• Once a function returns, its activation record cannot be referenced again • Register contents Local data
• Function closures – procedure and run-time context to define free • Access link – access nonlocal data
variables Temporaries

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas

Activation Record Example of Activation Records


• Fields in an activation record Actual parameters global
• Control link – Points to the activation record main() integer 𝑎[11]
variable main() integer 𝑎[11]
of the caller Returned values

• Returned values – Space for the value to be main main


Control link rdArr()
returned
rdArr
• Actual parameters – Space for actual Access link
parameters integer 𝑖 local
Saved machine
variable
status

• Contents and position of fields may vary Local data Frame for main() rdArr() is activated

with language and implementations Temporaries

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas


What is in G’s Activation Record when F()
Example of Activation Records
calls G()?
• If a procedure F calls G, then G’s activation record contains
main() integer 𝑎[11]
information about both F and G
main
• F is suspended until G completes, at which point F resumes
rdArr() qsort(1,9)
integer 𝑚, 𝑛 • G’s activation record contains information needed to resume execution of F
qsort(1,9) • G’s activation record contains
integer 𝑖 local • G’s return value (needed by F)
variable • Actual parameters to G (supplied by F)
• Space for G’s local variables
rdArr() is popped, qsort(1,9) is pushed

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas

A Standard Procedure Linkage Calling Sequence


• Procedure linkage is a procedure p • Calling sequence allocates an activation record on the stack and
contract between the prologue enters information into its fields
compiler, the OS, and the procedure q
• Responsibility is shared between the caller and the callee
target machine prologue • Return sequence is code to restore the state of the machine so the
• Divides responsibility for precall
calling procedure can continue its execution after the call
naming, allocation of
resources, addressability, postreturn
epilogue
and protection

epilogue

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas

Division of Tasks Between Caller and Callee


Calling Sequence

• Policies and implementation strategies can differ
Caller’s activation record

• Place values communicated between caller and callee at the beginning of the Parameters and return value
callee’s activation record, close to the caller's activation record
Control link
• Fixed-length items are placed in the middle
Caller’s responsibility

Links and saved status


• Data items whose size are not known during intermediate code generation Temporaries and local data
are placed at the end of the activation record
Callee’s activation record

• Top-of-stack points to the end of the fixed-length fields Parameters and return value
• Fixed-length data items are accessed by fixed offsets from top-of-stack pointer
responsibility

Control link
• Variable-length fields records are actually "above" the top-of-stack Links and saved status
Caller’s

top_stack
Temporaries and local data

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas


Division of Tasks Between Caller and Callee Division of Tasks Between Caller and Callee

Call sequence Return Sequence


• Caller evaluates the actual parameters • Callee places the return value next to the parameters
• Caller stores a return address and the old value of top_stack into • Callee restores top_stack and other registers
the callee's activation record • Callee branches to the return address that the caller placed in the
• Caller then increments top_stack past the caller's local data and status field
temporaries and the callee's parameters and status fields • Caller copies return value into its activation record
• Callee saves the register values and other status information
• Callee initializes its local data and begins execution

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas

Communication between Procedures Call by Value and Call by Reference


• Calling convention is an implementation-level detail to specify Call by Value Call by Reference
how callees receive parameters from their caller and how callees
return a result • Convention where the caller • Convention where the compiler
evaluates the actual parameters passes an address for the formal
• Parameter binding maps the actual parameters at a call site to the and passes their r-values to the
parameter to the callee
callee’s formal parameters callee
• Any redefinition of a reference
• Types of mapping conventions • Formal parameter in the callee is formal parameter is reflected in
treated like a local name
• Pass by value the corresponding actual
• Any modification of a value parameter
• Pass by reference parameter in the callee is not
• Pass by name visible in the caller • A formal parameter requires an
• Example: C and Pascal extra indirection
CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas

Call by Name Challenges with Call by Name


• Reference to a formal parameter procedure double(x); procedure swap(a, b) • What will happen when you call
behaves as if the actual parameter real x; integer a, b, temp; swap(i, x[i])?
begin begin
had been textually substituted in
x := x*2 temp := a
its place
end;
• Renaming is used in case of clashes a := b
• Can update the given parameters b := temp
double(c[j]) c[j] := c[j]*2
• Actual parameters are evaluated end;
inside the called function
• Example: Algol-60
https://www2.cs.sfu.ca/~cameron/Teaching/383/PassByName.html

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas


Nested Lexical Scopes in Pascal
Name Spaces program Main0(inp, op);
var x1, y1, z1: integer;

• Scope is the part of a program to which a name declaration applies procedure Fee1; Scope x y z
var x2: integer; Main <1,0> <1,4> <1,8>
• Scope rules provide control over access to data and names begin { Fee1 }
Fee <2,0> <1,4> <1,8>
x2 := 1;
• Lexical scope – a name refers to the definition that is lexically closest Fie <1,0> <2,0> <2,8>
y1 := x2*2+1
to the use end;
Foe <1,0> <2,0> <3,0>

• Compilers can use a static coordinate for a name for lexically-scoped procedure Fie1; Fum <1,0> <4,0> <3,0>

languages var y2: real;


procedure Foe2;
• Consider a name 𝑥 declared in a scope 𝑠
var z3: real;
• Static coordinate is a pair <𝑙, 𝑜> procedure Fum3;
• 𝑙 is the lexical nesting level of s and 𝑜 is the offset where 𝑥 is stored in the scope’s data var y4: real;
area
...

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas

Lexical and Dynamic Scoping Lexical and Dynamic Scope


• A variable that a procedure refers to and that is declared outside the int x = 1, y = 0; • What is the value of x after the
procedure’s own scope is called a free variable int g(int z) { call to g()?
return x + z;
• With lexical scoping, a free variable is bound to the declaration for its }
name that is lexically closest to the use int f(int y) { • Lexical scope: x = ?
• With dynamic scoping, a free variable is bound to the variable most int x;
recently created at runtime x = y + 1;
return g(x * y); • Dynamic scope: x = ?
• Lexical scoping is more popular
}
• Dynamic scoping is relatively challenging to implement
• Both are identical as far as local variables are concerned y=f(3);

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas

Lexical and Dynamic Scope Lexical and Dynamic Scoping in Perl


$x = 10;
sub f Dynamic scope
int x = 1, y = 0; • What is the value of x after the {
int g(int z) { call to g()? $ perl scope.pl
return $x;
return x + z; ?
}
} sub g
int f(int y) { • Lexical scope: x = 1 {
int x; # If local is used, x uses dynamic scoping
Lexical scope
x = y + 1; # If my is used, x uses lexical scoping
return g(x * y); • Dynamic scope: x = 4 local $x = 20; $ perl scope.pl
} # my $x = 20; ?
return f();
}
y=f(3);
print g()."\n";

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas


Lexical and Dynamic Scoping in Perl Scoping Rules for C and Java Languages
$x = 10;
Global scope Public classes
sub f Dynamic scope a, b, c, …
{
File scope File scope package p1 package p2
return $x; $ perl scope.pl
static names static names …
20
} x, y, z w, x, z public class A
sub g fields
foo bar method f1
{ variables variables local variables
# If local is used, x uses dynamic scoping parameters … method f2
Lexical scope labels
# If my is used, x uses lexical scoping local variables
package p3
local $x = 20; $ perl scope.pl fee …
Block scope class B
# my $x = 20; 10
variables Block scope fields
return f(); labels variables method f3
}
print g()."\n";

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas

Allocating Activation Records Variable Length Data on the Stack


• Data may be local to a procedure …

Activation record for 𝑃


• Stack allocation but the size may not be known Control link
• Activation records follow LIFO ordering at compile time Links and saved status
• For example, a local array whose …
• E.g.: Pascal, C, and Java Pointer to 𝑎
size depends upon a parameter
• Heap allocation Pointer to 𝑏
• Data may be allocated in the Pointer to 𝑐
• Needed when a procedure can outlive its caller
heap but would require garbage …
• Garbage collection support eases complexity Array 𝑎
collection
• E.g.: Implementations of Scheme and ML Array 𝑏
• Possible to allocate variable- Array 𝑐

for 𝑄 called from 𝑃


• Static allocation

Activation record
sized local data on the stack …
• Procedure 𝑃 cannot have multiple active invocations if it does not call other Control link
procedures Links and saved status
top_stack …
CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas

Data Access without Nested Procedures Access to Nonlocal Data in Nested Procedures
• Consider C-family of languages • This is challenging for nested procedures
• Any name local to a procedure is nonlocal to other procedures
• Suppose procedure 𝑝 at lexical level 𝑚 is nested in procedure 𝑞 at
• Simple rules level 𝑛, and 𝑥 is declared in 𝑞
• Global variables are in static storage • Our aim is to resolve a nonlocal name 𝑥 in 𝑝
• Addresses are fixed and determined at compile time
• Any other name must be local to the activation at the top of the stack
• Compiler models the reference by a static distance coordinate <𝑚 −
𝑛, 𝑜> where 𝑜 is 𝑥’s offset in the activation record for 𝑞
• Compiler needs to translate <𝑚 − 𝑛, 𝑜> into a runtime address

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas


Access to Nonlocal Data in Nested Procedures Access Links
• Finding the relevant activation of 𝑞 from an activation of 𝑝 is a • Suppose procedure 𝑝 is nested immediately Actual parameters

dynamic decision within procedure 𝑞 Returned values


• We cannot use compile-time decisions since there could be many activation • Access link in any activation of 𝑝 points to
records of 𝑝 and 𝑞 on the stack Control link
the most recent activation of 𝑞
• Access links form a chain up the nesting Access link
• Two common strategies: access links and displays hierarchy Saved machine
• All activations whose data and procedures are status
accessible to the currently executing procedure Local data

Temporaries

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas

Nesting Depth Quicksort in ML using Nested Procedures


1) fun sort (inputFile, outputFile) = 7) fun quicksort(m,n) =

• Procedures not nested within other procedures have nesting depth 1 let let
2) val a = array(11,O); 8) val v= ... ;
• For example, all functions in C have depth 1
3) fun readArray(inputFi1e) = ... ; 9) fun partition(y,z) =
• If 𝑝 is defined immediately within a procedure at depth 𝑖, then 𝑝 is at 4) ...a... ; 10) ...a...v...exchange...
depth 𝑖 + 1 5) fun exchange(i, j) = in
6) ...a... ; 11) ...a...v...partition...quicksort
end

Procedure Nesting Depth in


sort 1 12) ...a...readArray...quicksort...
readArray 2 end;
exchange 2
quicksort 2
partition 3
CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas

How to find nonlocal 𝑥? Example of Access Links


sort
• Suppose procedure 𝑝 is at the top of the stack and has depth 𝑛𝑝 , and access link
𝑞 is a procedure that surrounds 𝑝 and has depth 𝑛𝑞 𝑎
• Usually 𝑛𝑞 < 𝑛𝑝 , 𝑛𝑞 == 𝑛𝑝 only if 𝑝 and 𝑞 are the same qsort(1,9) Why?
access link Because sort called quicksort?
𝑣
• Follow the access link (𝑛𝑝 − 𝑛𝑞 ) times to reach an activation record
for 𝑞
• That activation record for 𝑞 will contain a definition for local 𝑥

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas


Example of Access Links Example of Access Links
sort sort sort
access link access link access link
𝑎 𝑎 𝑎
qsort(1,9) Why? qsort(1,9) Why? qsort(1,9)
access link Because sort called quicksort? access link access link
𝑣 𝑣 𝑣
No, because sort is the most closely nested qsort(1,3)
Because sort called quicksort?
function surrounding quicksort
access link
No, because sort is the most closely nested
𝑣
function surrounding quicksort

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas

Coordinate Code
Example of Access Links sort
Manipulating Access Links
<2, 24> loadAI rarp, 24 ⇒ r2
access link <1, 12> loadAI rarp, aloff ⇒ r1
loadAI r1, 12 ⇒ r2
𝑎
sort sort sort Level 0 <0, 16> loadAI rarp, aloff ⇒ r1
qsort(1,9) loadAI r1, aloff ⇒ r1
access link access link access link Level 1 Actual loadAI r1, 16 ⇒ r2
access link parameters
𝑎 𝑎 𝑎 Level 2 Actual
𝑣 parameters Returned
qsort(1,9) qsort(1,9) qsort(1,9) Actual
Returned values
qsort(1,3) parameters
access link access link access link Returned values Control link
access link values
𝑣 𝑣 𝑣 Control link
𝑣 Access link
ARP Control link
qsort(1,3) qsort(1,3) Access link Saved machine
part(1,3)
access link access link Access link Saved machine status
access link status
𝑣 𝑣 Saved machine Local data
status Local data
part(1,3) Temporaries
exchg(1,3) Local data
access link Temporaries
access link
Temporaries

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas

Manipulating Access Links Manipulating Access Links


• Code to setup access links is part of the calling sequence • Case 1: 𝑛𝑞 < 𝑛𝑝
• Suppose procedure 𝑞 at depth 𝑛𝑞 calls procedure 𝑝 at depth 𝑛𝑝 • Called procedure 𝑝 is nested more deeply than 𝑞
• Therefore, 𝑝 must be declared in 𝑞, or the call by 𝑞 will not be within the
• The code for setting up access links depends upon whether or not the scope of 𝑝
called procedure is nested within the caller • Access link in 𝑝 should point to the access link of the activation record of the
caller 𝑞
• Case 2: 𝑛𝑝 == 𝑛𝑞
• Procedures are at the same nesting level
• Access link of called procedure 𝑝 is the same as 𝑞

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas


sort
Manipulating Access Links access link Displays
𝑎
qsort(1,9)
• Case 3: 𝑛𝑞 > 𝑛𝑝 • Display is a global array to hold the activation record pointers for the
access link
• For the call within 𝑞 to be in the scope of 𝑝, 𝑞 must most recent activations of procedures at each lexical level
be nested within some procedure 𝑟, while 𝑝 is 𝑣
defined immediately within 𝑟 qsort(1,3)
d[1] d[1]
• Top activation record for 𝑟 can be found by access link
following chain of access links for 𝑛𝑞 − 𝑛𝑝 + 1 hops d[2] sort d[2] sort
𝑣
• Start in the activation record for 𝑞
part(1,3)
• Access link for 𝑞 will go to the activation for 𝑟 qsort(1,9) qsort(1,9)
access link
null null
• Nesting depth of exchange is 2 exchg(1,3)
… …
qsort(1,3)
• Nesting depth of partition is 3 access link
saved d[2]

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas


Insight in Using Displays Displays d[1]


d[2] sort
d[3]
d[1]
• Suppose a procedure 𝑝 is executing and needs to access element 𝑥 qsort(1,9)
d[2] sort
belonging to procedure 𝑞 null
d[3]

• The runtime only needs to search in activations from 𝑑[𝑖], where 𝑖 is qsort(1,9)
qsort(1,3)
the nesting depth of 𝑞 null
saved d[2]
• Follow the pointer 𝑑[𝑖] to the activation record for 𝑞, wherein 𝑥 should be …
defined at a known offset …
qsort(1,3)
partn(1,3)
saved d[2] null
… …
partn(1,3)
exchg(1,3)
null saved d[2]
… …
CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas

Access Links vs Displays Heap Management


Access Links Displays • Few runtime structures can outlive the called procedure
• Cost of lookup varies • Cost of lookup is constant • Heap is used for allocating space for objects created at runtime
• Common case is cheap, but long • Interface to the heap: allocate(size) and free(addr)
chains can be costly • Commonly-used interfaces
• malloc()/free() in C or new/delete in C++
• Cost of maintenance also is • Cost of maintenance is constant
variable • Allocation and deallocation may be completely manual (C/C++), semi-
automatic (Java), or fully automatic (Lisp)

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas


Heap Management Heap Management
• Manages heap memory by implementing mechanisms for allocation • First-fit allocation – emphasize speed over memory utilization
and deallocation • Every block in the heap has a field for size
• Either manual or automatic strategies
• Goals size
size
• Space efficiency – minimize fragmentation
next
• Program efficiency – take advantage of locality of objects in memory and
make the program run faster Allocated block Free block

• Low overhead – allocation and deallocation must be efficient

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas

First-Fit Allocation Reducing Fragmentation


• allocate(k) • Merge free blocks
• Traverse the free list to find a block bi with size greater than k+1 • Check the preceding end-of-block pointer when processing bj
• If found, remove bi from the free list and return pointer to the second word of • Merge if both blocks are free
bi • Can also merge with successor block
• If bi is larger than k, then split the extra space and add to the free list
• If not found, then request for more virtual memory • Other variants – best-fit and next-fit allocation strategy
• Best-fit strategy searches and picks the smallest (best) possible chunk that
• free(addr)
satisfies the allocation request
• Add bj to the head of the free list
• Next-fit strategy tries to allocate the object in the chunk that has been split
recently

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas

Problems with Manual Deallocation References


• Common problems • A. Aho et al. Compilers: Principles, Techniques, and Tools, 2nd edition, Chapter 7.1-7.4.
• K. Cooper and L. Torczon. Engineering a Compiler, 2nd edition, Chapter 6, 7.1-7.2.
• Fail to delete data that is not required, called memory leak
• Critical for performance of long-running or server programs
• Reference deleted data, i.e., dangling pointer reference
• These problems are hard to debug

• Possible solution is support for implicit deallocation


• Garbage collection is support for implicit deallocation of objects that
reside on the runtime heap

CS 335 Swarnendu Biswas CS 335 Swarnendu Biswas


Symbol Table
Symbol Table
The data structure that is created and
maintained by the compilers for information
storing regarding the occurrence of various
entities like names of variables, functions,
objects, classes
Symbol table is used by both the analysis
and the synthesis parts of a compiler

Information Stored in Symbol


Symbol Table Table
A symbol table may serve the following The following possible information about
purposes depending upon the language in identifiers are stored in symbol table
hand: The name (as a string)
To store the names of all entities in a structured Attribute: Reserved word, Variable name, Type
form at one place name, Procedure name, Constant name
To verify if a variable has been declared The data type
To implement type checking, by verifying The block level
assignments and expressions in the source code Its scope (global, local, or parameter)
are semantically correct Its offset from the base pointer (for local variables
To determine the scope of a name (scope and parameters only)
resolution)

Implementation Entry Format


Symbol table can be implemented as A symbol table maintains an entry for each
Unordered List name in the following format:
Linear (sorted or unsorted) list <symbol name, type, attribute>
Binary Search Tree For example, if a symbol table has to store
Hash table information about the following variable
Among all, symbol tables are mostly declaration:
implemented as hash tables, where the static int interest;
source code symbol itself is treated as a key
then it should store the entry such as:
for the hash function and the return value is
the information about the symbol. <interest, int, static>
Operations Operations
A symbol table, either linear or hash, should An attribute for a symbol in the source code is the
information associated with that symbol.
provide the following operations. This information contains the value, state, scope, and type
insert() about the symbol.
This operation is more frequently used by analysis The insert() function takes the symbol and its
phase where tokens are identified and names are attributes as arguments and stores the information in
stored in the table. the symbol table.
This operation is used to add information in the For example:
symbol table about unique names occurring in the int a;
source code. should be processed by the compiler as:
The format or structure in which the names are stored insert(a, int);
depends upon the compiler in hand.

Operations Operations
lookup() This method returns 0 (zero) if the symbol does not
lookup() operation is used to search a name in the exist in the symbol table. If the symbol exists in the
symbol table to determine: symbol table, it returns its attributes stored in the
table.
if the symbol exists in the table.
if it is declared before it is being used.
if the name is used in the scope.
if the symbol is initialized.
if the symbol declared multiple times.
The basic format should match the following:
lookup(symbol)

Scope Management Scope Management


A compiler maintains multiple block levels of Symbol tables are arranged
symbol tables: in hierarchical structure as
Level 0: A null hash table at level 0 shown in the example below:
Level 1: Keyword in the hash table at level 1
Level 2: Global symbol table which can be
accessed by all the procedures
Level 4: Scope symbol tables that are created
for each scope in the program
Structure of the Symbol Table Structure of the Symbol Table
We will implement the symbol table as a Initially, we create a null hash table at level 0.
linked list of hash tables, one hash table for
each block level.

Level 3 Level 2 Level 1 Level 0 Level 0

Hash table Hash table Hash table


of of of null null
Locals Globals Keywords

Structure of the Symbol Table Structure of the Symbol Table


Then we increase the block level and install Then we increase the block level and install
the keywords in the symbol table at level 1. the globals at level 2.

Level 1 Level 0 Level 2 Level 1 Level 0

Hash table Hash table Hash table


of null of of null
Keywords Globals Keywords

Structure of the Symbol Table Structure of the Symbol Table


When we enter a function, we create a level 3 When we leave the function, the hash table of
hash table and store parameters and local local variables is deleted from the list.
variables there.

Level 3 Level 2 Level 1 Level 0 Level 2 Level 1 Level 0

Hash table Hash table Hash table Hash table Hash table
of of of null of of null
Locals Globals Keywords Globals Keywords
Locating a Symbol Locating a Symbol
If we enter another function, a new level 3 When we look up an identifier, we begin the
hash table is created. search at the head of the list.

Level 3 Level 2 Level 1 Level 0 Level 3 Level 2 Level 1 Level 0

Hash table Hash table Hash table Hash table Hash table Hash table
of of of null of of of null
Locals Globals Keywords Locals Globals Keywords

Locating a Symbol Locating a Symbol


If it is not found there, then the search Keywords are found in the level 1 hash table.
continues at the lower levels.

Level 3 Level 2 Level 1 Level 0 Level 3 Level 2 Level 1 Level 0

Hash table Hash table Hash table Hash table Hash table Hash table
of of of null of of of null
Locals Globals Keywords Locals Globals Keywords

Symbol table example Symbol table example cont.


class Foo {

int value; (Foo)


int test() { Symbol Kind Type Properties
int b = 3;
scope of b value field int …
return value + b;
} test method -> int
void setValue(int c) { setValue method int -> void
value = c; scope of value
{ int d = c;
c = c + d;
scope of d scope of c (Test) (setValue)
block1 value = c;
Symbol Kind Type Properties Symbol Kind Type Properties
}
} b var int … c var int …
}

class Bar { (block1)


int value; Symbol Kind Type Properties
void setValue(int c) { d var int …
value = c;
} scope of c scope of value
}
23 24
Checking scope rules Catching semantic errors
Error !
(Foo)
(Foo) Symbol Kind Type Properties
Symbol Kind Type Properties
value field int …
value field int … test method -> int
test method -> int setValue method int -> void
setValue method int -> void

(Test) (setValue)
(Test) (setValue) Symbol Kind Type Properties Symbol Kind Type Properties
Symbol Kind Type Properties Symbol Kind Type Properties
b var int … c var int …
b var int … c var int …

(block1)
(block1) void setValue(int c) { lookup(myValue) Symbol Kind Type Properties
void setValue(int c) { lookup(value) Symbol Kind Type Properties value = c; d var int …
value = c; d var int …
{ int d = c;
{ int d = c; c = c + d;
c = c + d; myValue = c;
value = c; }
} }
25 26
}

Hash Tables Hash Tables


A hash table is a list in which each member is The numerical value of the hashed key gives
accessed through a key. the location of the member.
The key is used to determine where to store Thus, there is no need to search for the
the value in the table. member; the hashed key tells where it is
The function that produces a location from located.
the key is called the hash function. For example, if the string were "return",
For example, if it were a hash table of strings, then the key would be (114 + 101 + 116 +
the hash function might compute the sum of 117 + 114) % 100 = 62.
the ASCII values of the first 5 characters of Thus, "return" would be located in position
the string, modulo the size of the table. 62 of the hash table.

Clashes and Buckets Hash Table Efficiency


Clearly, there is the possibility of a clash: two The two parameters that determine how
members have the same hashed key. efficiently the hash table performs are
In that case, the hash table creates a list, The capacity of the table, i.e., the total amount of
called a “bucket,” of those values in the table memory allocated.
with that same location. The number of buckets, or equivalently, the size
When that location comes up, the list is of a bucket.
searched. Clearly, the size of a bucket times the
However, it is generally a very short list, number of buckets equals the capacity of the
especially if the table size has been chosen table.
well.
Hash Table Efficiency
For a given hash table capacity, End of Chapter # 13
If there are too many buckets, then many buckets
will not be used, leading to space inefficiency.
If there are too few buckets, then there will be
many clashes, causing the searches to
degenerate into predominately sequential
searches, leading to time inefficiency.

Design Of a Compiler

CODE OPTIMIZATION S ource code

L exical A nalysis

S yntax A nalysis
Table Error
M gmt
Routine
Intermediate Code Generation Handling
Routine
Presented By:
Code Optimization
Amita das
Jayanti bhattacharya Code Generation

Jaistha Upadhyay
Object code

What is optimization?
 In computing, optimization is the process of modifying a system to make
some aspect of it work more efficiently or use fewer resources. F or
instance, a computer program may be optimized so that it executes more
rapidly, or is capable of operating with less memory storage or other
resources, or draw less power. The system may be a single computer
program, a collection of computers or even an entire network such as the
internet.
Levels' of optimization
 Assembly level
Optimization can occur at a number of 'levels':
 Design level
A t the lowest level, writing code using an A ssembly language designed for
a particular hardware platform will normally produce the most efficient
A t the highest level, the design may be optimized to make best use code since the programmer can take advantage of the full repertoire of
of the available resources. The implementation of this design will machine instructions. The operating systems of most machines has been
benefit from the use of suitable efficient algorithms and the traditionally written in A ssembler code for this reason.
implementation of these algorithms will benefit from writing good
quality code. The architectural design of a system overwhelmingly
affects its performance. The choice of algorithm affects efficiency  Runtime
more than any other item of the design.
 Compile level
Just In Time Compiler and assembler programmers are able to perform
runtime optimization.
Use of an optimizing compiler tends to ensure that the executable
program is optimized at least as much as the compiler can predict.

Criteria For optimization


When to optimize ?
A n optimization must preserve the meaning of a
program :
-Cannot change the output produced for any input
Optimization is often performed at the end of the development
stage since it -Can not introduce an error
• reduces readability optimization should, on average, speed up programs
• adds code that is used to improve the performance.
Transformation should be worth the effort

Improvements can be made at various phases:


Types of Code optimization
Source Code:
-A lgorithms transformations can produce spectacular improvements
-Profiling can be helpful to focus a programmer’s attention on important code.  Common S ub-expression Removal
Intermediate Code:  Dead Code Optimization
-Compiler can improve loops, procedure calls and address calculations  Loop Optimization
-Typically only optimizing compilers include this phase
Target Code:
-Compilers can use registers efficiently
-Peephole transformation can be applied
Common Sub expression elimination
Dead code Optimization:
Common S ub expression elimination is a optimization that
searches for instances of identical expressions (i.e they all
evaluate the same value), and analyses whether it is worthwhile Dead Code elimination is a compiler optimization that removes code that does not
replacing with a single variable holding the computed value. affect a program. Removing such code has two benefits It shrinks program size, an
important consideration in some contexts. It lets the running program avoid
executing irrelevant operations, which reduces its running time.
a=b * c + g temp=b * c
a=temp + g
d=b * c * d
d=temp * d Dead Code elimination is of two types
Unreachable Code
Redundant statement

Unreachable Code Redundant Code


Redundant Code is code that is executed but has
no effect on the output from a program
In Computer Programming, Unreachable Code or dead code is code that exists
in the source code of a program but can never be executed.
main(){
int a,b,c,r;
Program Code Optimized Code
a=5;
If (a>b)
If (a>b) b=6;
m=a
elseif (a<b) m=a c=a + b;
Adding time & space complexity
elseif (a<b)
m=b r=2;
elseif (a==b) m=b
else
r++;
m=0
else m=0 printf(“ %d” ,c);
m=-1 }

Loop Invariant
Loop optimization
i =1 i =1
L oop optimization plays an important role in improving the s= 0 s= 0
performance of the source code by reducing overheads
do{ a =5
associated with executing loops.
s= s + i do{

a =5 s= s + i
L oop Optimization can be done by removing:
i =i +1 i =i +1
• L oop invariant
{ {
• Induction variables
while (i < =n) while (i < =n)

Bringing a=5 outside the do while loop, is called code


motion.
Induction variables
i=1 i=1
s= 0 s= 0
S1=0 S1=0
S2=0 S2=0
while (i < =n) t2=0
{ while (i < =n)
s= s + a[ i ] {
t1 = i * 4 s= s + a[ i ] “+” replaced “ * ”,
s= s + b[ t1 ] t1 = t1+ 4 t1 was made
t2 = t1 +2 s= s + b[ t1 ] independent of i
s2= s2 + c[ t2 ] s2= s2 + c[t1 +2 ]
i=i+1 i=i+1
} }

t1,t2 are induction variables. i is inducing t1 and t1 is inducing t2

Common Sub-expression Removal

 It is used to remove redundant computations which usually improves


the execution time of a program.
Three Address Code of Quick Sort Find The Basic Block
1 i=m-1 16 t7 = 4 * I 1 i=m-1 16 t7 = 4 * I
2 j=n 17 t8 = 4 * j 2 j=n 17 t8 = 4 * j
3 t1 =4 * n 18 t9 = a[t8] 3 t1 =4 * n 18 t9 = a[t8]
4 v = a[t1] 19 a[t7] = t9 4 v = a[t1] 19 a[t7] = t9
5 i=i +1 20 t10 = 4 * j 5 i=i +1 20 t10 = 4 * j
6 t2 = 4 * i 21 a[t10] = x 6 t2 = 4 * i 21 a[t10] = x
7 t3 = a[t2] 22 goto (5) 7 t3 = a[t2] 22 goto (5)
8 if t3 < v goto (5) 23 t11 = 4 * I 8 if t3 < v goto (5) 23 t11 = 4 * i
9 j=j–1 24 x = a[t11] 9 j=j–1 24 x = a[t11]
10 t4 = 4 * j 25 t12 = 4 * i 10 t4 = 4 * j 25 t12 = 4 * i
11 t5 = a[t4] 26 t13 = 4 * n 11 t5 = a[t4] 26 t13 = 4 * n
12 if t5 > v goto (9) 27 t14 = a[t13] 12 if t5 > v goto (9) 27 t14 = a[t13]
13 if i >= j goto (23) 28 a[t12] = t14 13 if i >= j goto (23) 28 a[t12] = t14
14 t6 = 4 * i 29 t15 = 4 * n 14 t6 = 4 * i 29 t15 = 4 * n
15 x = a[t6] 30 a[t15] = x 15 x = a[t6] 30 a[t15] = x

B1 Flow Graph B1 Common Subexpression Elimination


i=m-1 i=m-1
j=n j=n
t1 =4 * n t1 =4 * n
v = a[t1] B5 B6 v = a[t1] B5 B6
B2 t6 = 4 * i t11 = 4 * i B2 t6 = 4 * i t11 = 4 * i

i=i +1 x = a[t6] x = a[t11] i=i +1 x = a[t6] x = a[t11]


t2 = 4 * i t7 = 4 * i t12 = 4 * i t2 = 4 * i t7 = 4 * i t12 = 4 * i
t3 = a[t2] t8 = 4 * j t13 = 4 * n t3 = a[t2] t8 = 4 * j t13 = 4 * n
if t3 < v goto B2 t9 = a[t8] if t3 < v goto B2 t9 = a[t8]
t14 = a[t13] t14 = a[t13]
B3 a[t7] = t9 a[t12] = t14
B3 a[t7] = t9 a[t12] = t14
j=j–1 t10 = 4 * j j=j–1 t10 = 4 * j
t15 = 4 * n t15 = 4 * n
t4 = 4 * j t4 = 4 * j
a[t10] = x a[t15] = x a[t10] = x a[t15] = x
t5 = a[t4] t5 = a[t4]
goto B2 goto B2
if t5 > v goto B3 if t5 > v goto B3

B4 B4
if i >= j goto B6 if i >= j goto B6

B1 Common Subexpression Elimination B1 Common Subexpression Elimination


i=m-1 i=m-1
j=n j=n
t1 =4 * n t1 =4 * n
v = a[t1] B5 B6 v = a[t1] B5 B6
B2 t6 = 4 * i t11 = 4 * i B2 t6 = 4 * i t11 = 4 *i

i=i +1 x = a[t11] i=i +1 x = a[t11]


x = a[t6] x = a[t6]
t2 = 4 * i t12 = 4 * i t2 = 4 * i t12 = 4 * i
t8 = 4 * j t8 = 4 * j
t3 = a[t2] t13 = 4 * n t3 = a[t2] t13 = 4 * n
t9 = a[t8] t9 = a[t8]
if t3 < v goto B2 if t3 < v goto B2
t14 = a[t13] t14 = a[t13]
a[t6] = t9 a[t6] = t9
B3 a[t12] = t14
B3 a[t12] = t14
t10 = 4 * a[t8] = x
j=j–1 j=j–1
j t15 = 4 * n t15 = 4 * n
t4 = 4 * j t4 = 4 * j goto B2
a[t10] = x a[t15] = x a[t15] = x
t5 = a[t4] t5 = a[t4]
if t5 > v goto B3 goto B2 if t5 > v goto B3

B4 B4
if i >= j goto B6 if i >= j goto B6
B1 Common Subexpression Elimination B1 Common Subexpression Elimination
i=m-1 i=m-1
j=n j=n
t1 =4 * n t1 =4 * n
v = a[t1] B5 B6 v = a[t1] B5 B6
B2 t6 = 4 * i t11 = 4 * i B2 t6 = 4 * i t11 = 4 * i

i=i +1 x = a[t11] i=i +1 x = a[t11]


x = a[t6] x = a[t6]
t2 = 4 * i t12 = 4 * i t2 = 4 * i t13 = 4 * n
t8 = 4 * j t8 = 4 * j
t3 = a[t2] t13 = 4 * n t3 = a[t2] t14 = a[t13]
t9 = a[t8] t9 = a[t8]
if t3 < v goto B2 if t3 < v goto B2
t14 = a[t13] a[t11] = t14
a[t6] = t9 a[t6] = t9
B3 a[t12] = t14
B3 t15 = 4 * n
a[t8] = x a[t8] = x
j=j–1 j=j–1
t15 = 4 * n a[t15] = x
t4 = 4 * j goto B2 t4 = 4 * j goto B2
a[t15] = x
t5 = a[t4] t5 = a[t4]
if t5 > v goto B3 if t5 > v goto B3

B4 B4
if i >= j goto B6 if i >= j goto B6

B1 Common Subexpression Elimination B1 Common Subexpression Elimination


i=m-1 i=m-1
j=n j=n
t1 =4 * n t1 =4 * n
v = a[t1] B5 B6 v = a[t1] B5 B6
B2 t6 = 4 * i B2 t6 = 4 * i
t11 = 4 * i t11 = 4 * i
i=i +1 x = a[t11] i=i +1 x = a[t11]
x = a[t6] x = a[t6]
t2 = 4 * i t2 = 4 * i
t8 = 4 * j t13 = 4 * n t8 = 4 * j t13 = 4 * n
t3 = a[t2] t3 = a[t2]
t9 = a[t8] t14 = a[t13] t9 = a[t8] t14 = a[t13]
if t3 < v goto B2 if t3 < v goto B2
a[t6] = t9 a[t11] = t14 a[t6] = t9 a[t11] = t14
B3 B3
a[t8] = x a[t13] = x a[t8] = x a[t13] = x
j=j–1 j=j–1
t4 = 4 * j goto B2 t4 = 4 * j goto B2

t5 = a[t4] t5 = a[t4]
if t5 > v goto B3 if t5 > v goto B3

B4 B4
if i >= j goto B6 if i >= j goto B6

B1 Common Subexpression Elimination B1 Common Subexpression Elimination


i=m-1 i=m-1
j=n j=n
t1 =4 * n t1 =4 * n
v = a[t1] B5 B6 v = a[t1] B5 B6
B2 x = a[t2] B2 x = t3
t11 = 4 * i t11 = 4 * i
i=i +1 t8 = 4 * j i=i +1 t8 = 4 * j
x = a[t11] x = a[t11]
t2 = 4 * i t9 = a[t8] t2 = 4 * i t9 = a[t8]
t13 = 4 * n t13 = 4 * n
t3 = a[t2] a[t2] = t9 t3 = a[t2] a[t2] = t9
t14 = a[t13] t14 = a[t13]
if t3 < v goto B2 a[t8] = x if t3 < v goto B2 a[t8] = x
a[t11] = t14 a[t11] = t14
B3 goto B2 B3 goto B2
a[t13] = x a[t13] = x
j=j–1 j=j–1
t4 = 4 * j t4 = 4 * j
t5 = a[t4] t5 = a[t4]
if t5 > v goto B3 if t5 > v goto B3

B4 B4
if i >= j goto B6 if i >= j goto B6
B1 Common Subexpression Elimination B1 Common Subexpression Elimination
i=m-1 i=m-1
j=n j=n
t1 =4 * n t1 =4 * n
v = a[t1] B5 B6 v = a[t1] B5 B6
B2 x = t3 B2 x = t3
t11 = 4 * i x = t3
i=i +1 a[t2] = t5 i=i +1 a[t2] = t5
x = a[t11] t14 = a[t1]
t2 = 4 * i a[t4] = x t2 = 4 * i a[t4] = x
t13 = 4 * n a[t2] = t14
t3 = a[t2] goto B2 t3 = a[t2] goto B2
t14 = a[t13] a[t1] = x
if t3 < v goto B2 if t3 < v goto B2
a[t11] = t14
B3 B3
a[t13] = x Similarly for B6
j=j–1 j=j–1
t4 = 4 * j t4 = 4 * j
t5 = a[t4] t5 = a[t4]
if t5 > v goto B3 if t5 > v goto B3

B4 B4
if i >= j goto B6 if i >= j goto B6

B1 Dead Code Elimination B1 Dead Code Elimination


i=m-1 i=m-1
j=n j=n
t1 =4 * n t1 =4 * n
v = a[t1] B5 B6 v = a[t1] B5 B6
B2 x = t3 B2 a[t2] = t5 t14 = a[t1]
x = t3
a[t2] = t5 a[t4] = t3 a[t2] = t14
i=i +1 t14 = a[t1] i=i +1
t2 = 4 * i a[t4] = x t2 = 4 * i goto B2 a[t1] = t3
a[t2] = t14
t3 = a[t2] goto B2 t3 = a[t2]
a[t1] = x
if t3 < v goto B2 if t3 < v goto B2
B3 B3
j=j–1 j=j–1
t4 = 4 * j t4 = 4 * j
t5 = a[t4] t5 = a[t4]
if t5 > v goto B3 if t5 > v goto B3

B4 B4
if i >= j goto B6 if i >= j goto B6

B1 Reduction in Strength B1 Reduction in Strength


i=m-1 i=m-1
j=n j=n
t1 =4 * n t1 =4 * n
v = a[t1] B5 B6 v = a[t1] B5 B6
t2 = 4 * i
B2 a[t2] = t5 t14 = a[t1] B2 a[t2] = t5 t14 = a[t1]
t4 = 4 * j
a[t4] = t3 a[t2] = t14 a[t4] = t3 a[t2] = t14
i=i +1
t2 = 4 * i goto B2 a[t1] = t3 goto B2 a[t1] = t3
t3 = a[t2] t2 = t2 + 4
if t3 < v goto B2 t3 = a[t2]

B3 B3 if t3 < v goto B2
j=j–1
t4 = 4 * j t4 = t4 - 4
t5 = a[t4] t5 = a[t4]
if t5 > v goto B3 if t5 > v goto B3

B4 B4
if i >= j goto B6 if i >= j goto B6

You might also like