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

Chapter5 1 Merged

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)
11 views

Chapter5 1 Merged

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/ 192

Chapter 5

Syntax-Directed
Translation
outline
• the translation of languages guided by context-free
grammars.
• A syntax-directed definition specifies the values of
attributes by associating semantic rules with the
grammar productions.
We associate information with a language construct
by attaching attributes to the grammar symbol(s)
representing the construct,
outline
• a syntax-directed translation scheme embeds
program fragments called semantic actions
within production bodies.
E → El +T { print ' + ' }
The position of a semantic action in a production
body determines the order in which the action is
executed.
in general, semantic actions may occur at any
position in a production body.
outline
• The most general approach to syntax-
directed translation is to construct a parse
tree or a syntax tree, and then to compute
the values of attributes at the nodes of the
tree by visiting the nodes of the tree.
• a class of syntax-directed translations called
"L-attributed translations "
• a smaller class, called "S-attributed
translations" (S for synthesized )
5.1 Syntax-Directed Definitions

• A syntax-directed definition (SDD) is a context-free


grammar together with attributes and rules.
• Attributes are associated with grammar symbols and
rules are associated with productions.
• X.a : denote the value of a at a particular parse-tree
node labeled X.
• Attributes may be of any kind: numbers, types, table
references, or strings, for instance.
5.1.1 Inherited and Synthesized Attributes

• A synthesized attribute: for a nonterminal A


at a parse-tree node N is defined by a semantic
rule associated with the production at N.
the production must have A as its head. A
synthesized attribute at node N is defined only
in terms of attribute values at the children of
N and at N itself.
5.1.1 Inherited and Synthesized Attributes
• An inherited attribute for a nonterminal B at
a parse-tree node N is defined by a semantic
rule associated with the production at the
parent of N.
Note that the production must have B as a
symbol in its body. An inherited attribute at
node N is defined only in terms of attribute
values at N's parent, N itself, and N's
siblings.
5.1.1 Inherited and Synthesized Attributes
• we do not allow an inherited attribute at node N to
be defined in terms of attribute values at the
children of node N.
• we do allow a synthesized attribute at node N to
be defined in terms of inherited attribute values at
node N itself.
• Terminals can have synthesized attributes, but not
inherited attributes. Attributes for terminals have
lexical values that are supplied by the lexical
analyzer;
5.1.1 Inherited and Synthesized Attributes
• PRODUCTION •SEMANTIC RULES
1) L → E n L.val = E.val
2) E → E l + T E.val=E1.val+T.val
3) E → T E.val = T.val
4) T → Tl * F T.val=Tl.val  F.val
5) T → F T.val = F.val
6) F → ( E ) F.val = E.val
7) F → digit F. val = digit .lexval
S-attributed: An SDD that involves only synthesized
attributes is called S-attributed .
5.1.1 Inherited and Synthesized Attributes
• An S-attributed SDD can be implemented naturally in
conjunction with an LR parser.
• An SDD without side effects is sometimes called an
attribute grammar.
• The rules in an attribute grammar define the value of an
attribute purely in terms of the values of other attributes
and constants.
5.1.2 Evaluating an SDD at the Nodes
of a Parse Tree
• To visualize the translation specified by an
SDD, it helps to work with parse trees, even
though a translator need not actually build a
parse tree.
• annotated parse tree : A parse tree showing
the value(s) of its attribute(s).
5.1.2 Evaluating an SDD at the
Nodes of a Parse Tree

• How do we construct an annotated parse


tree?
• In what order do we evaluate attributes?
Before we can evaluate an attribute at a
node of a parse tree, we must evaluate all
the attributes upon which its value depends.
5.1.2 Evaluating an SDD at the
Nodes of a Parse Tree
• we can evaluate synthesized attributes in any bottom-
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.
5.1.2 Evaluating an SDD at the
Nodes of a Parse Tree
• Example 5.2

Figure 5.3: Annotated parse tree for 3 * 5 + 4 n


5.1.2 Evaluating an SDD at the
Nodes of a Parse Tree
• Inherited attributes are useful when the structure of a
parse tree does not "match" the abstract syntax of the
source code.

the left operand 3 appears


in a different subtree of
the parse tree from *.
An inherited attribute will
therefore be used to pass
the operand to the
operator.
5.1.2 Evaluating an SDD at the
Nodes of a Parse Tree
• Example 5.3 Each of the nonterminals T
and F has a synthesized
attribute val.
The terminal digit has a
synthesized attribute lexval.
The nonterminal T' has two
attributes: an inherited
attribute inh and a synthesized
attribute syn.

Figure 5.5: Annotated parse tree for 3 * 5


5.2 Evaluation Orders for SDD's

• "Dependency graphs" are a useful tool for


determining an evaluation order for the attribute
instances in a given parse tree.

two important classes of SDD's:


the "S-attributed"
the more general "L-attributed " SDD's.
5.2.1 Dependency Graphs
• A dependency graph depicts the flow of
information among the attribute instances in
a particular parse tree.
• Edges express constraints implied by the
semantic rules.
5.2.1 Dependency Graphs
• The dependency graph has a node for each attribute
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.
5.2.1 Dependency Graphs
• Example 5.4

Figure 5.6: E. val is synthesized from El. val and E2. val
5.2.1 Dependency Graphs
• Example 5.5

Figure 5.7: Dependency graph for the annotated parse tree of Fig. 5.5
5.2.2 Ordering the Evaluation of Attributes
• the only allowable orders of evaluation are those
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
least one topological sort.
5.2.3 S-Attributed Definitions
• An SDD is S-attributed if every attribute is
synthesized.
Example 5.7 : The SDD of Fig. 5.1 is an example of
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


attributes in any bottom up order of the nodes of the
parse tree. (performing a postorder traversal of the parse
tree)
5.2.3 S-Attributed Definitions
postorder (N) {
for ( each child C of N, from the left ) postorder(C);
evaluate the attributes associated with node N;
}

S-attributed definitions can be implemented during


bottom-up parsing, since a bottom-up parse
corresponds to a postorder traversal.
5.2.4 L-Attributed Definitions

• between the attributes associated with a


production body, dependency-graph edges can
go from left to right, but not from right to left
(hence "L-attributed").
5.2.4 L-Attributed Definitions
each attribute must be either
• Synthesized, or
• Inherited, but with the rules limited as follows.
Suppose that there is a production A → X 1X2 …… Xn,
and that there is an inherited attribute Xi.a computed
by a rule associated with this production.
(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
• Example 5.8 : The SDD in Fig. 5.4 is L-attributed.

Example 5.9 : Any SDD containing the following


production and rules cannot be L-attributed:
5.2.5 Semantic Rules with Controlled Side
Effects
• 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.
• Translation schemes impose left-to-right evaluation and
allow semantic actions to contain any program fragment.
5.2.5 Semantic Rules with Controlled
Side Effects
• control side effects in SDD's in one of the
following ways:
• Permit incidental side effects that do not
constrain attribute evaluation.
• Constrain the allowable evaluation orders, so
that the same translation is produced for any
allowable order.
5.2.5 Semantic Rules with Controlled
Side Effects
• Example 5.10 : The SDD in Fig. 5.8 takes a simple
declaration D consisting of a basic type T followed by a
list L of identifiers.
1) D → T L L.inh = T.type
2) T → int T. type = integer
3) T → float T.type = float
4) L → L1 , id Ll.inh=L.inh
addType(id.entry, L.inh)
5) L → id add Type(id entry, L.inh)
5.2.5 Semantic Rules with Controlled
Side Effects

Figure 5.9: Dependency graph for a declaration float idl,id2,id3


5.3 Applications of Syntax-Directed
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.
5.3.1 Construction of Syntax Trees

• If the node is a leaf, an additional field holds the


lexical value for the leaf. A constructor function
Leaf ( op, val ) creates a leaf object.
• If the node is an interior node, there are as many
additional fields as the node has children in the
syntax tree. A constructor function Node takes two
or more arguments: Node(op, cl, c2, . . . , ck)
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
expression grammar involving only the binary
operators +and -.
PRODUCTION SEMANTIC RULES
1) E → E1 + T E.node = new Node('+', E1 .node, T.node)
2) E → E1 - T E.node = new Node('-', El .node, T.node)
3) E → T E.node = T.node
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
1) pl = new Leaf(id, entry-a);
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


5.3.1 Construction of Syntax Trees
• Example 5.12 : The L-attributed definition in Fig. 5.13

Figure 5.13: Constructing syntax trees during top-down parsing


5.3.1 Construction of Syntax Trees

Figure 5.14: Dependency graph for a - 4 + c, with the SDD of Fig. 5.13
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.15: Type


expression for int [2] [3]
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


5.3.2 The Structure of a Type

Figure 5.17: Syntax-directed translation of array types


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

Semester 2019-2020-II
CSE, IIT Kanpur

Content influenced by many excellent references, see References slide for acknowledgements.
An Overview of Compilation
source program target program

lexical analyzer code generator


symbol table

syntax analyzer error handler code optimizer

intermediate code
semantic analyzer
generator

CS 335 Swarnendu Biswas


Abstraction Spectrum
• Translating source code requires dealing with all programming
language abstractions
• For example, names, procedures, objects, flow of control, and exceptions
• Physical computer operates in terms of several primitive operations
• Arithmetic, data movement, and control jumps
• It is not enough to just translate intermediate code to machine code
• For e.g., need to manage memory when a program is executing

CS 335 Swarnendu Biswas


Runtime Environment
• A runtime environment is a set of data structures maintained at run
time to implement high-level structures
• For example, stack, heap, static area, and virtual function tables
• Depends on the features of the source and the target language
• Compilers create and manage a runtime environment in which the
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


Issues Dealt with Runtime Environments
• How to pass parameters when a procedure is called?
• What happens to locals when procedures return from an activation?
• How to support recursive procedures?
• Can a procedure refer to nonlocal names? If yes, then how?
•…

CS 335 Swarnendu Biswas


Storage Organization
• Target program runs in its own logical space Code
• Size of generated code is usually fixed at compile time Static
• Unless code is loaded or produced dynamically
Heap
• Compiler can place the executable at fixed addresses
• Runtime storage can be subdivided into
• Target code Free Memory
• Static data objects such as global constants
• Stack to keep track of procedure activations and local data Stack
• Heap to keep all other information like dynamic data

CS 335 Swarnendu Biswas


Strategies for Storage Allocation
• Static allocation – Lay out storage at compile time only by studying
the program text
• Memory allocated at compile time will be in the static area
• Dynamic allocation – Storage allocation decisions are made when the
program is running
• Stack allocation – Manage run-time allocation with a stack storage
• Local data are allocated on the stack
• Heap allocation – Memory allocation and deallocation can be done at any
time
• Requires memory reclamation support

CS 335 Swarnendu Biswas


Static Allocation
• Names are bound to storage locations at compilation time
• Bindings do not change, so no run time support is required
• Names are bound to the same location on every invocation
• Values are retained across activations of a procedure
• Limitations
• Size of all data objects must be known at compile time
• Data structures cannot be created dynamically
• Recursive procedures are not allowed

CS 335 Swarnendu Biswas


Stack vs Heap Allocation
Stack Heap

• Allocation/deallocation is • Allocation/deallocation is explicit


automatic
• Less expensive • More expensive
• Space for allocation is limited • Challenge is fragmentation

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

CS 335 Swarnendu Biswas


Procedure Abstraction

CS 335 Swarnendu Biswas


Procedure Calls
• Procedure definition is a declaration that associates an identifier with
a statement (procedure body)
• Formal parameters appear in declaration
• Actual parameters appear when a procedure is called

• Important abstraction in programming


• Defines critical interfaces among large parts of a software

CS 335 Swarnendu Biswas


Procedure Calls
• Creates a controlled execution environment
• Each procedure has its own private named storage or name space
• Executing a call instantiates the callee’s name space

• Abstractions provided by procedures


• Control abstraction
• Name space
• External interface

CS 335 Swarnendu Biswas


Control Abstraction
• Each language has rules to
• Invoke a procedure
• Map a set of arguments from the caller’s name space to the callee’s name
space
• Return control to the caller, and continue execution after the call
• Linkage convention standardizes the actions taken by the compiler
and the OS to make a procedure call

CS 335 Swarnendu Biswas


Procedure Calls
• Each execution of a procedure 𝑃 is an activation of the procedure 𝑃
• A procedure is recursive if an activation can begin before an earlier
activation of the same procedure has ended
• If procedure is recursive, several activations may be alive at the same time

• The lifetime of an activation of 𝑃 is all the steps to execute 𝑃


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


Activation Tree
• Depicts the way control enters and leaves int g() { return 42; }
activations int f() { return g(); }

• Root represents the activation of main main() {


g();
• Each node represents activation of a
procedure f():

• Node 𝑎 is the parent of 𝑏 if control flows }


from 𝑎 to 𝑏
• Node 𝑎 is to the left of 𝑏 if lifetime of 𝑎 main
occurs before 𝑏
• Flow of control in a program corresponds g f
to depth-first traversal of activation tree
g

CS 335 Swarnendu Biswas


Quicksort Code
int a[11]; void quicksort(int m, int n) {
void readArray() { int i;
int i; if (n > m) {
… i = partition(m, n);
} quicksort(m, i-1);
quicksort(i+1, n);
int partition(int m, int n) { } }

} int main() {
readArray();
a[0] = -99999;
a[10] = 99999;
quicksort(1, 9);
}

CS 335 Swarnendu Biswas


Activation Tree
main() Also referred to as dynamic
call graph

rdArr() qsort(1,9)

partn (1,9) qsort(1,3) qsort(5,9)

partn (5,9) qsort(5,5) qsort(7,9)


partn (1,3) qsort(1,0) qsort(2,3)

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

CS 335 Swarnendu Biswas


enter main()

Example of Procedure Activations enter readArray()


leave readArray()
enter quicksort(1,9)
enter partition(1,9)
main()
leave partition(1,9)
enter quicksort(1,3)
...
rdArr() qsort(1,9)
leave quicksort(1,3)
enter quicksort(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 (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)

CS 335 Swarnendu Biswas


Control Stack
• Procedure calls and returns are usually managed by
a run-time stack called the control stack qsort(2,3)
• Each live activation has an activation record on the
control stack qsort(1,3)
• Stores control information and data storage needed to
manage the activation qsort(1,9)
• Also called a frame
main()
• Frame is pushed when activation begins and popped
when activation ends
• Suppose node 𝑛 is at the top of the stack, then the
stack contains the nodes along the path from 𝑛 to
the root
CS 335 Swarnendu Biswas
Is a Stack Sufficient?
When will a control stack work?
• Once a function returns, its activation record cannot be referenced again
• We do not need to store old nodes in the activation tree
• Every activation record has either finished executing or is an ancestor of
the current activation record
When will a control stack not work?
• Once a function returns, its activation record cannot be referenced again
• Function closures – procedure and run-time context to define free
variables
CS 335 Swarnendu Biswas
Is a Stack Sufficient?
When will a control stack work?
• Once a function returns, its activation record cannot be referenced again
• We do not need to store old nodes in the activation tree
• Every activation record has either finished executing or is an ancestor of
the current activation record
When will a control stack not work?
• Once a function returns, its activation record cannot be referenced again
• Function closures – procedure and run-time context to define free
variables
CS 335 Swarnendu Biswas
Activation Record
• A pointer to the current activation record Actual parameters
is maintained in a register
Returned values
• Fields in an activation record
• Temporaries – evaluation of expressions Control link
• Local data – field for local data
Access link
• Saved machine status – information about the
machine state before the procedure call Saved machine
status
• Return address (value of program counter)
• Register contents Local data
• Access link – access nonlocal data
Temporaries

CS 335 Swarnendu Biswas


Activation Record
• Fields in an activation record Actual parameters
• Control link – Points to the activation record
of the caller Returned values

• Returned values – Space for the value to be Control link


returned
• Actual parameters – Space for actual Access link
parameters
Saved machine
status

• Contents and position of fields may vary Local data

with language and implementations Temporaries

CS 335 Swarnendu Biswas


Example of Activation Records

global
main() variable main()
integer 𝑎[11] integer 𝑎[11]

main main
rdArr()
rdArr

integer 𝑖 local
variable

Frame for main() rdArr() is activated

CS 335 Swarnendu Biswas


Example of Activation Records

main() integer 𝑎[11]

main
rdArr() qsort(1,9)
integer 𝑚, 𝑛

qsort(1,9)

integer 𝑖 local
variable

rdArr() is popped, qsort(1,9) is pushed

CS 335 Swarnendu Biswas


What is in G’s Activation Record when F()
calls G()?
• If a procedure F calls G, then G’s activation record contains
information about both F and G
• F is suspended until G completes, at which point F resumes
• G’s activation record contains information needed to resume execution of F
• G’s activation record contains
• G’s return value (needed by F)
• Actual parameters to G (supplied by F)
• Space for G’s local variables

CS 335 Swarnendu Biswas


A Standard Procedure Linkage
• Procedure linkage is a procedure p

contract between the prologue


compiler, the OS, and the procedure q

target machine prologue


• Divides responsibility for precall

naming, allocation of
resources, addressability, postreturn
epilogue
and protection

epilogue

CS 335 Swarnendu Biswas


Calling Sequence
• Calling sequence allocates an activation record on the stack and
enters information into its fields
• Responsibility is shared between the caller and the callee
• Return sequence is code to restore the state of the machine so the
calling procedure can continue its execution after the call

CS 335 Swarnendu Biswas


Calling Sequence
• Policies and implementation strategies can differ
• Place values communicated between caller and callee at the beginning of the
callee’s activation record, close to the caller's activation record
• Fixed-length items are placed in the middle
• Data items whose size are not known during intermediate code generation
are placed at the end of the activation record
• Top-of-stack points to the end of the fixed-length fields
• Fixed-length data items are accessed by fixed offsets from top-of-stack pointer
• Variable-length fields records are actually "above" the top-of-stack

CS 335 Swarnendu Biswas


Division of Tasks Between Caller and Callee

Caller’s activation record


Parameters and return value

Control link

Caller’s responsibility
Links and saved status

Temporaries and local data

Callee’s activation record


Parameters and return value

responsibility
Control link
Links and saved status

Caller’s
top_stack
Temporaries and local data

CS 335 Swarnendu Biswas


Division of Tasks Between Caller and Callee

Call sequence
• Caller evaluates the actual parameters
• Caller stores a return address and the old value of top_stack into
the callee's activation record
• Caller then increments top_stack past the caller's local data and
temporaries and the callee's parameters and status fields
• Callee saves the register values and other status information
• Callee initializes its local data and begins execution

CS 335 Swarnendu Biswas


Division of Tasks Between Caller and Callee

Return Sequence
• Callee places the return value next to the parameters
• Callee restores top_stack and other registers
• Callee branches to the return address that the caller placed in the
status field
• Caller copies return value into its activation record

CS 335 Swarnendu Biswas


Communication between Procedures
• Calling convention is an implementation-level detail to specify
how callees receive parameters from their caller and how callees
return a result
• Parameter binding maps the actual parameters at a call site to the
callee’s formal parameters
• Types of mapping conventions
• Pass by value
• Pass by reference
• Pass by name

CS 335 Swarnendu Biswas


Call by Value and Call by Reference
Call by Value Call by Reference

• Convention where the caller • Convention where the compiler


evaluates the actual parameters passes an address for the formal
and passes their r-values to the
callee parameter to the callee
• Any redefinition of a reference
• Formal parameter in the callee is formal parameter is reflected in
treated like a local name
the corresponding actual
• Any modification of a value parameter
parameter in the callee is not
visible in the caller • A formal parameter requires an
• Example: C and Pascal extra indirection
CS 335 Swarnendu Biswas
Call by Name
• Reference to a formal parameter procedure double(x);

behaves as if the actual parameter real x;


begin
had been textually substituted in
x := x*2
its place
end;
• Renaming is used in case of clashes
• Can update the given parameters
double(c[j]) c[j] := c[j]*2
• Actual parameters are evaluated
inside the called function
• Example: Algol-60
https://www2.cs.sfu.ca/~cameron/Teaching/383/PassByName.html

CS 335 Swarnendu Biswas


Challenges with Call by Name
procedure swap(a, b) • What will happen when you call
integer a, b, temp; swap(i, x[i])?
begin
temp := a
a := b
b := temp
end;

CS 335 Swarnendu Biswas


Name Spaces
• Scope is the part of a program to which a name declaration applies
• Scope rules provide control over access to data and names
• Lexical scope – a name refers to the definition that is lexically closest
to the use
• Compilers can use a static coordinate for a name for lexically-scoped
languages
• Consider a name 𝑥 declared in a scope 𝑠
• Static coordinate is a pair <𝑙, 𝑜>
• 𝑙 is the lexical nesting level of s and 𝑜 is the offset where 𝑥 is stored in the scope’s data
area

CS 335 Swarnendu Biswas


Nested Lexical Scopes in Pascal
program Main0(inp, op);
var x1, y1, z1: integer;
procedure Fee1; Scope x y z
var x2: integer; Main <1,0> <1,4> <1,8>
begin { Fee1 }
Fee <2,0> <1,4> <1,8>
x2 := 1;
Fie <1,0> <2,0> <2,8>
y1 := x2*2+1
Foe <1,0> <2,0> <3,0>
end;
procedure Fie1; Fum <1,0> <4,0> <3,0>
var y2: real;
procedure Foe2;
var z3: real;
procedure Fum3;
var y4: real;
...

CS 335 Swarnendu Biswas


Lexical and Dynamic Scoping
• A variable that a procedure refers to and that is declared outside the
procedure’s own scope is called a free variable
• With lexical scoping, a free variable is bound to the declaration for its
name that is lexically closest to the use
• With dynamic scoping, a free variable is bound to the variable most
recently created at runtime
• Lexical scoping is more popular
• Dynamic scoping is relatively challenging to implement
• Both are identical as far as local variables are concerned

CS 335 Swarnendu Biswas


Lexical and Dynamic Scope
int x = 1, y = 0; • What is the value of x after the
int g(int z) { call to g()?
return x + z;
}
int f(int y) { • Lexical scope: x = ?
int x;
x = y + 1;
return g(x * y); • Dynamic scope: x = ?
}

y=f(3);

CS 335 Swarnendu Biswas


Lexical and Dynamic Scope
int x = 1, y = 0; • What is the value of x after the
int g(int z) { call to g()?
return x + z;
}
int f(int y) { • Lexical scope: x = 1
int x;
x = y + 1;
return g(x * y); • Dynamic scope: x = 4
}

y=f(3);

CS 335 Swarnendu Biswas


Lexical and Dynamic Scoping in Perl
$x = 10;
sub f Dynamic scope
{
return $x; $ perl scope.pl
?
}
sub g
{
# If local is used, x uses dynamic scoping
Lexical scope
# If my is used, x uses lexical scoping
local $x = 20; $ perl scope.pl
# my $x = 20; ?
return f();
}
print g()."\n";

CS 335 Swarnendu Biswas


Lexical and Dynamic Scoping in Perl
$x = 10;
sub f Dynamic scope
{
return $x; $ perl scope.pl
20
}
sub g
{
# If local is used, x uses dynamic scoping
Lexical scope
# If my is used, x uses lexical scoping
local $x = 20; $ perl scope.pl
# my $x = 20; 10
return f();
}
print g()."\n";

CS 335 Swarnendu Biswas


Scoping Rules for C and Java Languages
Global scope Public classes
a, b, c, …
File scope File scope package p1 package p2
static names static names …
x, y, z w, x, z public class A
fields
foo bar method f1
variables variables local variables
parameters … method f2
labels local variables
package p3
fee …
Block scope class B
variables Block scope fields
labels variables method f3

CS 335 Swarnendu Biswas


Allocating Activation Records
• Stack allocation
• Activation records follow LIFO ordering
• E.g.: Pascal, C, and Java
• Heap allocation
• Needed when a procedure can outlive its caller
• Garbage collection support eases complexity
• E.g.: Implementations of Scheme and ML
• Static allocation
• Procedure 𝑃 cannot have multiple active invocations if it does not call other
procedures

CS 335 Swarnendu Biswas


Variable Length Data on the Stack
• Data may be local to a procedure …

Activation record for 𝑃


but the size may not be known Control link
at compile time Links and saved status
• For example, a local array whose …
size depends upon a parameter Pointer to 𝑎
Pointer to 𝑏
• Data may be allocated in the Pointer to 𝑐
heap but would require garbage …
collection Array 𝑎
Array 𝑏
• Possible to allocate variable- Array 𝑐

for 𝑄 called from 𝑃


Activation record
sized local data on the stack …
Control link
Links and saved status
top_stack …
CS 335 Swarnendu Biswas
Data Access without Nested Procedures
• Consider C-family of languages
• Any name local to a procedure is nonlocal to other procedures

• Simple rules
• Global variables are in static storage
• Addresses are fixed and determined at compile time
• Any other name must be local to the activation at the top of the stack

CS 335 Swarnendu Biswas


Access to Nonlocal Data in Nested Procedures
• This is challenging for nested procedures

• Suppose procedure 𝑝 at lexical level 𝑚 is nested in procedure 𝑞 at


level 𝑛, and 𝑥 is declared in 𝑞
• Our aim is to resolve a nonlocal name 𝑥 in 𝑝

• 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


Access to Nonlocal Data in Nested Procedures
• Finding the relevant activation of 𝑞 from an activation of 𝑝 is a
dynamic decision
• We cannot use compile-time decisions since there could be many activation
records of 𝑝 and 𝑞 on the stack

• Two common strategies: access links and displays

CS 335 Swarnendu Biswas


Access Links
• Suppose procedure 𝑝 is nested immediately Actual parameters

within procedure 𝑞 Returned values


• Access link in any activation of 𝑝 points to
Control link
the most recent activation of 𝑞
• Access links form a chain up the nesting Access link
hierarchy Saved machine
• All activations whose data and procedures are status
accessible to the currently executing procedure Local data

Temporaries

CS 335 Swarnendu Biswas


Nesting Depth
• Procedures not nested within other procedures have nesting depth 1
• For example, all functions in C have depth 1
• If 𝑝 is defined immediately within a procedure at depth 𝑖, then 𝑝 is at
depth 𝑖 + 1

CS 335 Swarnendu Biswas


Quicksort in ML using Nested Procedures
1) fun sort (inputFile, outputFile) = 7) fun quicksort(m,n) =
let let
2) val a = array(11,O); 8) val v= ... ;
3) fun readArray(inputFi1e) = ... ; 9) fun partition(y,z) =
4) ...a... ; 10) ...a...v...exchange...
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
How to find nonlocal 𝑥?
• Suppose procedure 𝑝 is at the top of the stack and has depth 𝑛𝑝 , and
𝑞 is a procedure that surrounds 𝑝 and has depth 𝑛𝑞
• Usually 𝑛𝑞 < 𝑛𝑝 , 𝑛𝑞 == 𝑛𝑝 only if 𝑝 and 𝑞 are the same

• 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


Example of Access Links
sort
access link
𝑎
qsort(1,9) Why?
access link Because sort called quicksort?
𝑣

CS 335 Swarnendu Biswas


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

CS 335 Swarnendu Biswas


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

CS 335 Swarnendu Biswas


Example of Access Links sort
access link
𝑎
sort sort sort
qsort(1,9)
access link access link access link
access link
𝑎 𝑎 𝑎
𝑣
qsort(1,9) qsort(1,9) qsort(1,9)
qsort(1,3)
access link access link access link
access link
𝑣 𝑣 𝑣
𝑣
qsort(1,3) qsort(1,3)
part(1,3)
access link access link
access link
𝑣 𝑣
part(1,3)
exchg(1,3)
access link
access link

CS 335 Swarnendu Biswas


Coordinate Code
<2, 24> loadAI rarp, 24 ⇒ r2
Manipulating Access Links <1, 12> loadAI rarp, aloff ⇒ r1
loadAI r1, 12 ⇒ r2

Level 0 <0, 16> loadAI rarp, aloff ⇒ r1


loadAI r1, aloff ⇒ r1
Level 1 Actual loadAI r1, 16 ⇒ r2
Level 2 Actual parameters
parameters Returned
Actual
Returned values
parameters
Returned values Control link
values Control link
Access link
ARP Control link
Access link Saved machine
Access link Saved machine status
Saved machine status Local data
status Local data
Temporaries
Local data
Temporaries
Temporaries

CS 335 Swarnendu Biswas


Manipulating Access Links
• Code to setup access links is part of the calling sequence
• Suppose procedure 𝑞 at depth 𝑛𝑞 calls procedure 𝑝 at depth 𝑛𝑝
• The code for setting up access links depends upon whether or not the
called procedure is nested within the caller

CS 335 Swarnendu Biswas


Manipulating Access Links
• Case 1: 𝑛𝑞 < 𝑛𝑝
• Called procedure 𝑝 is nested more deeply than 𝑞
• Therefore, 𝑝 must be declared in 𝑞, or the call by 𝑞 will not be within the
scope of 𝑝
• 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


sort
Manipulating Access Links access link
𝑎
qsort(1,9)
• Case 3: 𝑛𝑞 > 𝑛𝑝
access link
• For the call within 𝑞 to be in the scope of 𝑝, 𝑞 must
be nested within some procedure 𝑟, while 𝑝 is 𝑣
defined immediately within 𝑟 qsort(1,3)
• Top activation record for 𝑟 can be found by access link
following chain of access links for 𝑛𝑞 − 𝑛𝑝 + 1 hops
𝑣
• Start in the activation record for 𝑞
part(1,3)
• Access link for 𝑞 will go to the activation for 𝑟
access link

• Nesting depth of exchange is 2 exchg(1,3)


• Nesting depth of partition is 3 access link

CS 335 Swarnendu Biswas


Displays
• Display is a global array to hold the activation record pointers for the
most recent activations of procedures at each lexical level

d[1] d[1]
d[2] sort d[2] sort

qsort(1,9) qsort(1,9)
null null
… …
qsort(1,3)
saved d[2]

CS 335 Swarnendu Biswas



Insight in Using Displays
• Suppose a procedure 𝑝 is executing and needs to access element 𝑥
belonging to procedure 𝑞
• The runtime only needs to search in activations from 𝑑[𝑖], where 𝑖 is
the nesting depth of 𝑞
• Follow the pointer 𝑑[𝑖] to the activation record for 𝑞, wherein 𝑥 should be
defined at a known offset

CS 335 Swarnendu Biswas


Displays d[1]
d[2] sort
d[3]
d[1]
qsort(1,9)
d[2] sort
null
d[3]

qsort(1,9)
qsort(1,3)
null
saved d[2]
… …
qsort(1,3)
partn(1,3)
saved d[2] null
… …
partn(1,3)
exchg(1,3)
null saved d[2]
… …
CS 335 Swarnendu Biswas
Access Links vs Displays
Access Links Displays

• Cost of lookup varies • Cost of lookup is constant


• Common case is cheap, but long
chains can be costly
• Cost of maintenance also is • Cost of maintenance is constant
variable

CS 335 Swarnendu Biswas


Heap Management
• Few runtime structures can outlive the called procedure
• Heap is used for allocating space for objects created at runtime
• Interface to the heap: allocate(size) and free(addr)
• Commonly-used interfaces
• malloc()/free() in C or new/delete in C++
• Allocation and deallocation may be completely manual (C/C++), semi-
automatic (Java), or fully automatic (Lisp)

CS 335 Swarnendu Biswas


Heap Management
• Manages heap memory by implementing mechanisms for allocation
and deallocation
• Either manual or automatic strategies
• Goals
• Space efficiency – minimize fragmentation
• Program efficiency – take advantage of locality of objects in memory and
make the program run faster
• Low overhead – allocation and deallocation must be efficient

CS 335 Swarnendu Biswas


Heap Management
• First-fit allocation – emphasize speed over memory utilization
• Every block in the heap has a field for size

size
size
next

Allocated block Free block

CS 335 Swarnendu Biswas


First-Fit Allocation
• allocate(k)
• Traverse the free list to find a block bi with size greater than k+1
• If found, remove bi from the free list and return pointer to the second word of
bi
• 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
• free(addr)
• Add bj to the head of the free list

CS 335 Swarnendu Biswas


Reducing Fragmentation
• Merge free blocks
• Check the preceding end-of-block pointer when processing bj
• Merge if both blocks are free
• Can also merge with successor block
• Other variants – best-fit and next-fit allocation strategy
• Best-fit strategy searches and picks the smallest (best) possible chunk that
satisfies the allocation request
• Next-fit strategy tries to allocate the object in the chunk that has been split
recently

CS 335 Swarnendu Biswas


Problems with Manual Deallocation
• Common problems
• 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


References
• 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.

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
Symbol Table
A symbol table may serve the following
purposes depending upon the language in
hand:
To store the names of all entities in a structured
form at one place
To verify if a variable has been declared
To implement type checking, by verifying
assignments and expressions in the source code
are semantically correct
To determine the scope of a name (scope
resolution)
Information Stored in Symbol
Table
The following possible information about
identifiers are stored in symbol table
The name (as a string)
Attribute: Reserved word, Variable name, Type
name, Procedure name, Constant name
The data type
The block level
Its scope (global, local, or parameter)
Its offset from the base pointer (for local variables
and parameters only)
Implementation
Symbol table can be implemented as
Unordered List
Linear (sorted or unsorted) list
Binary Search Tree
Hash table
Among all, symbol tables are mostly
implemented as hash tables, where the
source code symbol itself is treated as a key
for the hash function and the return value is
the information about the symbol.
Entry Format
A symbol table maintains an entry for each
name in the following format:
<symbol name, type, attribute>
For example, if a symbol table has to store
information about the following variable
declaration:
static int interest;
then it should store the entry such as:
<interest, int, static>
Operations
A symbol table, either linear or hash, should
provide the following operations.
insert()
This operation is more frequently used by analysis
phase where tokens are identified and names are
stored in the table.
This operation is used to add information in the
symbol table about unique names occurring in the
source code.
The format or structure in which the names are stored
depends upon the compiler in hand.
Operations
An attribute for a symbol in the source code is the
information associated with that symbol.
This information contains the value, state, scope, and type
about the symbol.
The insert() function takes the symbol and its
attributes as arguments and stores the information in
the symbol table.
For example:
int a;
should be processed by the compiler as:
insert(a, int);
Operations
lookup()
lookup() operation is used to search a name in the
symbol table to determine:
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)
Operations
This method returns 0 (zero) if the symbol does not
exist in the symbol table. If the symbol exists in the
symbol table, it returns its attributes stored in the
table.
Scope Management
A compiler maintains multiple block levels of
symbol tables:
Level 0: A null hash table at level 0
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
Scope Management
Symbol tables are arranged
in hierarchical structure as
shown in the example below:
Structure of the Symbol Table
We will implement the symbol table as a
linked list of hash tables, one hash table for
each block level.

Level 3 Level 2 Level 1 Level 0

Hash table Hash table Hash table


of of of null
Locals Globals Keywords
Structure of the Symbol Table
Initially, we create a null hash table at level 0.

Level 0

null
Structure of the Symbol Table
Then we increase the block level and install
the keywords in the symbol table at level 1.

Level 1 Level 0

Hash table
of null
Keywords
Structure of the Symbol Table
Then we increase the block level and install
the globals at level 2.

Level 2 Level 1 Level 0

Hash table Hash table


of of null
Globals Keywords
Structure of the Symbol Table
When we enter a function, we create a level 3
hash table and store parameters and local
variables there.

Level 3 Level 2 Level 1 Level 0

Hash table Hash table Hash table


of of of null
Locals Globals Keywords
Structure of the Symbol Table
When we leave the function, the hash table of
local variables is deleted from the list.

Level 2 Level 1 Level 0

Hash table Hash table


of of null
Globals Keywords
Locating a Symbol
If we enter another function, a new level 3
hash table is created.

Level 3 Level 2 Level 1 Level 0

Hash table Hash table Hash table


of of of null
Locals Globals Keywords
Locating a Symbol
When we look up an identifier, we begin the
search at the head of the list.

Level 3 Level 2 Level 1 Level 0

Hash table Hash table Hash table


of of of null
Locals Globals Keywords
Locating a Symbol
If it is not found there, then the search
continues at the lower levels.

Level 3 Level 2 Level 1 Level 0

Hash table Hash table Hash table


of of of null
Locals Globals Keywords
Locating a Symbol
Keywords are found in the level 1 hash table.

Level 3 Level 2 Level 1 Level 0

Hash table Hash table Hash table


of of of null
Locals Globals Keywords
Symbol table example
class Foo {
int value;
int test() {
int b = 3;
scope of b
return value + b;
}
void setValue(int c) {
value = c; scope of value
{ int d = c;
c = c + d;
scope of d scope of c
block1 value = c;
}
}
}

class Bar {
int value;
void setValue(int c) {
value = c;
} scope of c scope of value
}
23
Symbol table example cont.


(Foo)
Symbol Kind Type Properties

value field int …


test method -> int
setValue method int -> void

(Test) (setValue)
Symbol Kind Type Properties Symbol Kind Type Properties

b var int … c var int …

(block1)
Symbol Kind Type Properties

d var int …

24
Checking scope rules
(Foo)
Symbol Kind Type Properties

value field int …


test method -> int
setValue method int -> void

(Test) (setValue)
Symbol Kind Type Properties Symbol Kind Type Properties

b var int … c var int …

(block1)
void setValue(int c) { lookup(value) Symbol Kind Type Properties
value = c; d var int …
{ int d = c;
c = c + d;
value = c;
}
25
}
Catching semantic errors
Error !
(Foo)
Symbol Kind Type Properties

value field int …


test method -> int
setValue method int -> void

(Test) (setValue)
Symbol Kind Type Properties Symbol Kind Type Properties

b var int … c var int …

(block1)
void setValue(int c) { lookup(myValue) Symbol Kind Type Properties
value = c; d var int …
{ int d = c;
c = c + d;
myValue = c;
}
}
26
Hash Tables
A hash table is a list in which each member is
accessed through a key.
The key is used to determine where to store
the value in the table.
The function that produces a location from
the key is called the hash function.
For example, if it were a hash table of strings,
the hash function might compute the sum of
the ASCII values of the first 5 characters of
the string, modulo the size of the table.
Hash Tables
The numerical value of the hashed key gives
the location of the member.
Thus, there is no need to search for the
member; the hashed key tells where it is
located.
For example, if the string were "return",
then the key would be (114 + 101 + 116 +
117 + 114) % 100 = 62.
Thus, "return" would be located in position
62 of the hash table.
Clashes and Buckets
Clearly, there is the possibility of a clash: two
members have the same hashed key.
In that case, the hash table creates a list,
called a “bucket,” of those values in the table
with that same location.
When that location comes up, the list is
searched.
However, it is generally a very short list,
especially if the table size has been chosen
well.
Hash Table Efficiency
The two parameters that determine how
efficiently the hash table performs are
The capacity of the table, i.e., the total amount of
memory allocated.
The number of buckets, or equivalently, the size
of a bucket.
Clearly, the size of a bucket times the
number of buckets equals the capacity of the
table.
Hash Table Efficiency
For a given hash table capacity,
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.
End of Chapter # 13
CODE OPTIMIZATION

Presented By:
Amita das
Jayanti bhattacharya
Jaistha Upadhyay
Design Of a Compiler

S ource code

L exical A nalysis

S yntax A nalysis
Table Error
M gmt
Routine
Intermediate Code Generation Handling
Routine

Code Optimization

Code Generation

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
Optimization can occur at a number of 'levels':
 Design level

A t the highest level, the design may be optimized to make best use
of the available resources. The implementation of this design will
benefit from the use of suitable efficient algorithms and the
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
more than any other item of the design.
 Compile level

Use of an optimizing compiler tends to ensure that the executable


program is optimized at least as much as the compiler can predict.
 Assembly 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
code since the programmer can take advantage of the full repertoire of
machine instructions. The operating systems of most machines has been
traditionally written in A ssembler code for this reason.

 Runtime

Just In Time Compiler and assembler programmers are able to perform


runtime optimization.
When to optimize ?

Optimization is often performed at the end of the development


stage since it
• reduces readability
• adds code that is used to improve the performance.
Criteria For optimization

A n optimization must preserve the meaning of a


program :
-Cannot change the output produced for any input
-Can not introduce an error
optimization should, on average, speed up programs
Transformation should be worth the effort
Improvements can be made at various phases:

Source Code:
-A lgorithms transformations can produce spectacular improvements
-Profiling can be helpful to focus a programmer’s attention on important code.
Intermediate Code:
-Compiler can improve loops, procedure calls and address calculations
-Typically only optimizing compilers include this phase
Target Code:
-Compilers can use registers efficiently
-Peephole transformation can be applied
Types of Code optimization

 Common S ub-expression Removal


 Dead Code Optimization
 Loop Optimization
Common Sub expression elimination

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
replacing with a single variable holding the computed value.

a=b * c + g temp=b * c
a=temp + g
d=b * c * d
d=temp * d
Dead code Optimization:

Dead Code elimination is a compiler optimization that removes code that does not
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.

Dead Code elimination is of two types


Unreachable Code
Redundant statement
Unreachable Code

In Computer Programming, Unreachable Code or dead code is code that exists


in the source code of a program but can never be executed.

Program Code Optimized Code

If (a>b)
m=a If (a>b)

elseif (a<b) m=a

m=b elseif (a<b)

elseif (a==b) m=b

m=0 else

else m=0

m=-1
Redundant Code
Redundant Code is code that is executed but has
no effect on the output from a program

main(){
int a,b,c,r;
a=5;
b=6;
c=a + b;
Adding time & space complexity
r=2;
r++;
printf(“ %d” ,c);
}
Loop optimization

L oop optimization plays an important role in improving the


performance of the source code by reducing overheads
associated with executing loops.

L oop Optimization can be done by removing:


• L oop invariant
• Induction variables
Loop Invariant

i =1 i =1

s= 0 s= 0

do{ a =5

s= s + i do{

a =5 s= s + i

i =i +1 i =i +1

{ {

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
1 i=m-1 16 t7 = 4 * I
2 j=n 17 t8 = 4 * j
3 t1 =4 * n 18 t9 = a[t8]
4 v = a[t1] 19 a[t7] = t9
5 i=i +1 20 t10 = 4 * j
6 t2 = 4 * i 21 a[t10] = x
7 t3 = a[t2] 22 goto (5)
8 if t3 < v goto (5) 23 t11 = 4 * I
9 j=j–1 24 x = a[t11]
10 t4 = 4 * j 25 t12 = 4 * i
11 t5 = a[t4] 26 t13 = 4 * n
12 if t5 > v goto (9) 27 t14 = a[t13]
13 if i >= j goto (23) 28 a[t12] = t14
14 t6 = 4 * i 29 t15 = 4 * n
15 x = a[t6] 30 a[t15] = x
Find The Basic Block
1 i=m-1 16 t7 = 4 * I
2 j=n 17 t8 = 4 * j
3 t1 =4 * n 18 t9 = a[t8]
4 v = a[t1] 19 a[t7] = t9
5 i=i +1 20 t10 = 4 * j
6 t2 = 4 * i 21 a[t10] = x
7 t3 = a[t2] 22 goto (5)
8 if t3 < v goto (5) 23 t11 = 4 * i
9 j=j–1 24 x = a[t11]
10 t4 = 4 * j 25 t12 = 4 * i
11 t5 = a[t4] 26 t13 = 4 * n
12 if t5 > v goto (9) 27 t14 = a[t13]
13 if i >= j goto (23) 28 a[t12] = t14
14 t6 = 4 * i 29 t15 = 4 * n
15 x = a[t6] 30 a[t15] = x
B1 Flow Graph
i=m-1
j=n
t1 =4 * n
v = a[t1] B5 B6
B2 t6 = 4 * i t11 = 4 * i

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


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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

B4
if i >= j goto B6
B1 Reduction in Strength
i=m-1
j=n
t1 =4 * n
v = a[t1] B5 B6
t2 = 4 * i
B2 a[t2] = t5 t14 = a[t1]
t4 = 4 * j
a[t4] = t3 a[t2] = t14
goto B2 a[t1] = t3
t2 = t2 + 4
t3 = a[t2]

B3 if t3 < v goto B2

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

B4
if i >= j goto B6

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy