0% found this document useful (0 votes)
47 views26 pages

Memory Allocation Strategies in C

The document discusses various storage allocation strategies in programming, including static, stack, and heap allocations, highlighting their advantages and drawbacks. Static allocation is determined at compile time and can lead to wasted memory or insufficient space, while dynamic allocation through stack and heap allows for more flexibility during runtime. It also covers concepts like activation records, procedure calls, and code optimization techniques to improve program efficiency.
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)
47 views26 pages

Memory Allocation Strategies in C

The document discusses various storage allocation strategies in programming, including static, stack, and heap allocations, highlighting their advantages and drawbacks. Static allocation is determined at compile time and can lead to wasted memory or insufficient space, while dynamic allocation through stack and heap allows for more flexibility during runtime. It also covers concepts like activation records, procedure calls, and code optimization techniques to improve program efficiency.
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

Storage Organization

• 3 storage allocation strategies are available


1. static
2. stack
3. heap
2,3 comes under dynamic allocation
Static Allocation/static memory allocation
//The static memory allocation which will be used in C lang
• The allocation of memory during compilation time is known as static
memory allocation
• For normal variables, arrays memory will be allocated during compilation
time
• So once the memory was allocated during compilation time then its not
possible to change its size during run time/execution time
Drawbacks:
• We must know in advance regarding the size of the array
• If more memory is allocated than required then memory will be wasted
//if memory is allocated for a[100]elements but used for a[5] elements
• If less memory is allocated than required then it causes the pblms, bcz it
is not possible to perform corresponding operations //memory allocated
for a[10] but performing operations on a[10] elements
• insertion and deletion operations are very expensive, bcz more [Link]
elements need to be shifted.
In the ex: if we want to place 100 in the beginning
We want to make 5 shifts, if the array size then there will
be [Link] of shifts
• If we want to delete 10 then 4 shifts will be performed

In order to overcome these pblms dynamic allocation is used

Dynamic Allocation
• Allocation of memory during run time for the corresponding
variables/pgm
Stack Allocation
• Stack is a DS which works on the principle of LIFO
• Whenever a fn or procedure call occurs then an Activation Record will be
created for the corresponding fn and the Activation Record will be
pushed onto the top of the stack
• Here stack is used mainly for maintaining the fn or procedure
information, this info will resides in AR
• If there are 5 fn’s in the prg then 5 AR’s will be created for the
corresponding 5 fn’s
Drawbacks
• It supports dynamic allocation but slower than static allocation
• It supports recursion but references to non local variables after activation
record can’t be retained
 In order to overcome these pblms we use heap allocation
Heap Allocation
• The major advantage is it supports recursion as well as the references to
non local variables after the activation record can be retained
• Mainly used for implementing dynamic allocation
• In C dynamic memory allocation fn’s are malloc, realloc, etc….
//by using these fn’s we can allocate the memory, as well as size of already
allocated memory block can be changed and memory deallocation will also be
done
Run Time Storage Allocation
• Whenever we save any prg then the prg will be stored in hard disk
• During compilation also the prg resides in hard disk only
• But a CPU or processor can execute a prg only when a prg resides in
main memory
• After compilation, the compiler demands a block of memory from the OS
in order to store that pgm in main memory //bcz it’s the responsibility of
OS to manage resources such as memory,files, i/o devices etc
• OS allocates a free block of memory to the corresponding prg
• So the compiler uses that free block of memory in order to store that
compiled prg, which is known as run time storage allocation
• Run time is nthng but execution time, so how the prg is stored during
execution time
• Main memory can be divided into 4 parts //subdivision of main memory
• In b/w heap and stack there will be some free memory
• Code will be stored at low address space
• Heap will be stored at high address space
• We can call the structure as logical address space of a prg
Code
• During compilation only the size of the prg will be decided
• This code area mainly contains the target executable code
Static Data Area
• Mainly used for storing static variables and global variables
• Global variables are used through out the prg, where as static variable
means the value of the variable is persistent b/w different fn calls
Heap and Stack
• These are used mainly to utilize the space in effective manner
• Stack grows from high to low address space, whereas heap grows from
low to high address space // they grow opposite to each other
• Whenever a fn or procedure call occurs then an Activation Record will be
created for the corresponding fn and the Activation Record will be
pushed onto the top of the stack
• Heap is a dynamic DS
• In order to allocate memory at run time heap is used
• If there are too many fn’s then stack is used more often, so the free
memory is more occupied by the stack
• If there are too many pointer variables, so address allocation for these
pointer variables will be done with the help of heap. So the free memory
is more often used by the heap
Activation Record

• Whenever a procedure call occurs the information’s in the procedure


must be stored in a block of storage
• That block of records is known as Activation records or frame
• This activation record has some fields
• In a prgmg lang like C whenever a procedure call occurs the activation
record must be pushed on to the stack and whenever a procedure returns
that activation record is popped from the stack
temporaries
 This field is used to store the temporary values generated in a procedure.
For example to execute an expression a=x+y*z. so to store some
intermediate result we require some temporaries. So the temporary values
will be stored in the field of temporaries
Local data
 Used for storing local data in a procedure
Saved m/c status
 It is used for storing m/c status whenever a procedure call occurs. When a
procedure call occurs m/c status information like the value of the prg
counter, value of the m/c registers these must be saved in this field.
Whenever the procedure returns that information must be restored
Optional access link
 This is an optional link which is used to refer to the non local data of
other activation records
Optional control link
 It is also an optional field which is used to point to the callers activation
record.
 Suppose if procedure A() is calling procedure B() means the ctrl link of
B() activation record points to the activation record of A()
A()
{
B();
}
 Ctrl link means it points to activation record of the parents procedure
Actual parameters
 All the actual parameters will be stored
 Normally this field is used by the calling prg to supply actual parameters
to the called procedure
return value
 return values will be stored here, so that this field is used by the caller
procedure to send the return value to the calling procedure
 normally the sizes of these fields can be determined at the compile time
itself
Procedure Calls

• P(x1,x2,…..xn) here P is a procedure so the procedure must be called


with n parameters
• The three address stmt for this procedure call is
param x1
param x2
……..
param x3
call p,n
• Parameters must be evaluated first and then call procedure p and n is the
[Link] actual parameters
• Whenever a procedure call occurs some sequence actions must be done
• For ex: consider a C prg
• Here main is the calling procedure
• Add which is not in main is the called procedure
• Whenever the procedure call occurs in main some sequence of actions
must be done
1. The space must be allocated for the activation record(information about
procedures) of the called procedure. For ex. Local variables in the procedure,
parameters in the procedure and return address etc.. So whenever the prg is
executed the calling function is main() this will be executed. Whenever a
procedure call occurs execution of the main procedure is temporarily suspended
and jump is performed to the called procedure

• After executing the called procedure again the jump must be performed to
the calling procedure. because the execution must be resumed at this
point so the return address must be saved so after this only jump to the
called procedure must be performed
• Similarly after executing the called procedure a return must be performed
if you want to perform any return, return stmt must be used., otherwise
after executing the called procedure directly the ctrl will be return back to
the calling procedure. But before performing the jump operation some
sequence of actions will be done here also
1. The result of the called procedure must be stored in a known place
2. Activation record of the calling procedure must be restored(because now
the calling procedure will take over the ctrl)
3. jump is performed to the calling procedure
Displays
• Array of pointers to activation record
Principle Sources of Optimization
Code Optimization
• Improves the intermediate code
• Reduce the space occupied by the prg and also running time of the prg
Code optimization Techniques
• Common subexpression elimination
• Constant folding
• Copy propagation
• Dead code elimination
• Code motion
• Induction variable elimination and reduction in strength
 These techniques must preserve meaning of the prg
 It should not change the meaning of the prg and code improvement must
be done otherwise no need to apply code optimization
• If copy stmt is there we need to use right side of copy stmt instead of
LHS
• Optimization code is same like original code. But there is a possibility of
deleting x=a
• Here x is not used after this point means we can say that x is dead
• So we can eliminate copy stmt completely

• Normally more time is spent for executing the loop, so if we move the
code outside the loop then we can improve the running time
• If the expression computes the same result independent of [Link] times a
loop is executed means then only we can move that stmt outside the loop
i.e. if it is loop invariant expression
• x=y+z is not based on the loop.,every time x value is same so that stmt
can be moved outside the loop
• Induction variable means it is depending upon the loop control variable
like i,j etc. so that type of Induction variable must be eliminated
• Reduction in strength means expensive operations must be replaced by
cheaper operation. i.e. complex operations must be replaced by the
simpler operations.
• For ex. Multiplication can be replaced by addition, division can be
replaced by multiplication etc…
• Here the loop is executed 9 times, at each iteration the t value is increased
by 4. so this multiplication can be replaced by addition.
• So reduction in strength can be performed then induction variable i can
also be removed in the optimized code
• In the optimized code the t value should be initialized before while loop
Basic Block
• It’s a collection of stmts which are always executed in sequential manner
// seq of consecutive stmts exe in seq manner
• Any basic block should contain one entry and one exit points
• Ctrl enters into the block and executes all the stmts sequentially
• Once all the stmts in the block are executed then the ctrl will exit from
the block
• Basic block should not contain conditional ctrl stmts as well as
unconditional ctrl stmts in the middle of the block ( might present in the
first as well as last stmt)
Example
[Link]=0
2.I=1
3.T2=addr(A) – 4
4.T4=addr(B) – 4
5.T1=4*I
6.T3=T2[T1]
7. PROD=PROD+T3
8. I=I+1
[Link] I<=20 goto (5)
10. j=j+1
11. k=k+1
• Consider an example x=a+b+c
• As this instruction is not 3 addr code instr
t1=a+b
t2=t1+c
x=t2
Algorithm for partitioning a 3 addr code into basic block
• Rule 1: Determining the leaders
a) 1st stmt is a leader // The 1st stmt of the block is always treated as a leader
(1st instr from the ex)
b) The target of conditional or unconditional jump is a leader // 9th instr from
the ex, the target of this instr is 5 if the condition is true then we need to
goto 5, so the instr 5 will become the leader now
c) The stmt following the conditional or unconditional jump is a leader
//from the ex 10th instr will become the leader now
Rule 2: Determining the basic blocks
The basic block is formed starting at the 1st stmt of the leader and ends at
the next leader before stmt // as next leader is 5, so before 5 it is 4 so the
basic block ends at stmt 4
• Now consider an example
[Link]=0
2.I=1
3.T2=addr(A) – 4
4.T4=addr(B) – 4
5.T1=4*I
6.T3=T2[T1]
7. PROD=PROD+T3
8. I=I+1
[Link] I<=20 goto (5)
10. j=j+1
11. k=k+1
12. If j<=5 goto (7)
13. i=i+j
• partitioning the 3 addr stmts into basic blocks based on rules
• Rule 1: So 1, 5,7,10,13 are leaders
• Rule 2:
PROD=0
I=1
T2=addr(A) – 4 B1

T4=addr(B) – 4

T1=4*i
B2
T3=T2[T1]

PROD=PROD+T3
B3
I=I+1
If I<=20 goto B2

J=j+1
K=k+1
B4
If j<=5 goto B3

i=i+j
B5

// As 5th instr is in B2
Flow Graph
• It’s a directed graph in which the flow ctrl information is added to the
basic blocks
• It’s a collection of nodes where we can have some edges from one node
to another node
• Here the basic blocks will become the nodes of flow graphs
• So total of 5 nodes are there from our ex
• Edges will specify the flow of information from one block to another
block
• If there is an edge from B1 to B2 then we can say that B2 block
immediately follows the block B1
• From our ex B1 is the initial block it is hvng the 1st leader
• So 1st B1 will be executed then ctrl goes to B2 and B2 will be executed
then ctrl goes to B3
• So in B3 we find B2 , after executing B3 ctrl will goes to B2 now
• After that B4 will be executed and ctrl goes to B3 and after that B5 will
be executed
DAG Representation of Basic Block
• Directed Acyclic Graph
• DAG represents the structure of a basic block
1. In DAG internal(parent) node represent operators
2. Leaf nodes represents identifiers(names of variables), constants (values)
3. Internal node also represents result of an expressions
If t=a+b then

Applications of DAG
• Determining the common sub expressions
• Determining which names are used inside the block and computed
outside the block
• Determining which stmts of the block could have their computed value
outside the block
• Simplifying the list of quadruples by eliminating common sub
expressions
Construction of DAG for Basic Blocks
Examples
• Construct DAG for the expression
a+a*(b-c)+(b-c)*d
As () is hvng highest precedence we need to consider it from left side and then
need to multiply with a
In RHS we have same b-c but already calculated so need to perform * with d
Next perform + with both LHS and RHS results
Next add a to the result

• Construct DAG for the block


1.a=b+c
2. b=a-d
3. c=b+c
4. d=a-d
The 4th stmt is already calculated, as the value of d is not changes in the place of
b we can place d like b,d
• Construct DAG for the block
1.a=b+c
2. b=b-d
3. c=c+d
4. e=b+c

• Construct DAG for the block


1.d=b*c
2. e=a+b
3. b=b*c
4. a=e-d
Already b*c is calculated and values of them are not changed

• Construct DAG for the expression


a=b*-c + b*-c
Already b*-c has been computed so + will indicate two directions

• Construct DAG for the expression


a= (a*b+c) - (a*b+c)
Optimization/Transformation of Basic Blocks
• With the help of transformations we can improve the basic blocks/we can
optimize the basic blocks
• There are 2 types of transformations that can be applied to the basic
blocks
1. Structure Preserving Transformations
2. Algebraic Transformations
Structure Preserving Transformations
• It has 4 primary transformations
1. Common subexpression elimination
2. Dead code elimination
3. Renaming of temporary variables
4. Interchange of 2 independent adjacent stmts
1. Common subexpression elimination
• It has 4 stmts
• In the 1st and 3rd stmts also the RHS appears same i.e. y+z ,. But the 2nd
stmt redefines y., y is recomputed in 2nd stmt. Therefore the y in 1st stmt is
not equivalent to 3rd stmt
• So here in the 1st stmt x is computing x=y+z where as in 3rd stmt z is
computing z= x-w+z.
• So these are not common subexpressions it cannot be eliminated from the
basic block
2. Dead code elimination
A variable is said to be dead if it is not subsequently used in other basic blocks
or it is not subsequently used further
Assume B2 as final basic block. Here a is not used in B2. after particular point a
is not used. So we can say that a is the dead code so it can be safely removed
without changing the value of the basic block

3 Renaming of temporary variables


A temporary variable can be renamed with another temporary variable
If we want to rename a temporary variable into another temporary variable we
have to replace all the uses of temporary variable with the new name
So after 4th stmt all the t1 should be renamed as t3 then only the meaning of the
basic block will not be changed
4. Interchange of 2 independent adjacent stmts
Independent stmts means two stmts are not depending upon each other
Here 2nd stmt depends on 1st stmt
The 2nd and 3rd stmts are independent. So here in the RHS of t2- t3 is not used
whereas in the RHS of t3- t2 is not used
So now we can interchange t2 and t3 without changing the value

Loop Optimization
• Most execution time of a prg is spent on loops
• So if we decrease the [Link] instructions in an inner loop then the running
time of a prg can be improved
• So loop optimization is used to improve the running time of the prg
Loop Optimization Techniques
• Code motion
• Induction variable elimination and reduction in strength
• Loop Unrolling
• Loop Jamming
1. Code motion
• It moves the code outside the loop
• If an expression gives the same result independent of no. of times a loop
is executed then that expression can be placed outside the loop. This is
known as code motion/movement
• limit/2 is a loop invariant computation i.e. it doesn’t depend on the loop
• So limit/2 is assigned to a temporary variable which is executed only
once

2. Induction variable elimination and reduction in strength


• Induction variable is a loop control variable
• i is a loop control variable which is initialized as [Link] the while loop
every time i is going to be incremented. So this type of induction variable
can be eliminated
• Reduction in strength means expensive operations must be replaced by
the cheaper operations
• Each time y is increased by 4. so MUL can be replaced by ADD
3. Loop Unrolling
• This technique duplicates body of the loop multiple times in order to
decrease the [Link] times the loop condition is tested
• Here loop is executed 100 times and display() is appeared .if we duplicate
this function call i.e. 2 times function call is return in the body and then
we can decrease 100 to 50

4. Loop Jamming
• It combines bodies of 2 adjacent loops that would iterate the same [Link]
times
• Here both the loops are executed 100 times and these are the 2 adjacent
loops, so that we can combine these 2 loops into single loop. This is also
known as loop merging
Data-Flow Analysis
• Data flow analysis is a technique used in compiler design to analyze how
data flows through a program.
• It involves tracking the values of variables and expressions as they are
computed and used throughout the program, with the goal of identifying
opportunities for optimization and identifying potential errors.
• The basic idea behind data flow analysis is to model the program as a
graph, where the nodes represent program statements and the edges
represent data flow dependencies between the statements.
• The data flow information is then propagated through the graph, using a
set of rules and equations to compute the values of variables and
expressions at each point in the program.
Peephole Optimization
• This technique is applied to improve the performance of prg by
examining a short sequence of instr’s in a window(peephole) and replace
the instructions by a faster or short seq of instr
• peephole is nthng but a window, instead of examining the entire prg we
examine a short sequence of instr’s
• If there is any possibility we may replace short sequence of instr’s by
faster or short seq of instr
Peephole Optimization Techniques
1. Redundant Instruction Elimination
2. Removal of unreachable code
3. Flow-of-control optimizations
4. Algebraic simplifications
5. Machine idioms
Redundant Instruction Elimination
• Consider the instructions
MOV R0,a
MOV a, R0
If we exe the 1st instr a value will be moved into R0 //R0 contains a
If we exe the 2nd instr R0 will be moved to a
But R0 already contains a so no need to execute 2nd instr
If 2nd instruction is exe the result is not going to be changed
So we can eliminate the 2nd instr
After optimization the code is
MOV R0,a

Removal of Unreachable Code


• Eliminate(remove) the stmts which are unreachable(never executed)
i=0
if(i==1)
{
sum=0;
}
//through out the prg i should be 0 only
But the condition is false, so the block can be eliminated
So after optimization the code is
i==0
Ex:
int add(int a, int b)
{
int c=a+b;
return c;
printf(“%d”,c);
}
With the help of add fn we are adding 2 int values
This stmt printf(“%d”,c); will never executed so it can be eliminated // once
return is exec then it returns c value from called fn to the calling fn, so c value
wont return
The optimized code is
int add(int a, int b)
{
int c=a+b;
return c;
}
Flow-of-control optimizations
• Using peephole optimization unnecessary jumps can be eliminated
• Flow of ctrl is nthng but the ctrl will be transferred
From one place of the prg to another place
• In the example instead of moving from one label to another
label directly we can go to L3. so we can eliminate the multiple jumps
• So the code can be written as
Algebraic Simplifications
• Let the expression be x=x+0 (or) x=x*1
• The result of both the stmts will be x. the result of x is not going to be
changed
• So its not necessary to exec these stmts
• The stmts can be eliminated
• Here we can apply reduction in strength
• a=x^2 can will be replaced with a=x*x
• b=y/8 can will be replaced with b=y>>3 //>> right shift
Use of Machine Idioms
• It is the process of using powerful features of CPU instr
• So CPU instr are used for exec
• If we want to perform addition operation
a=a+1 can be written as INC a
• a=a-1 can be written as DEC a

You might also like