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

CD Lab Manual

The document outlines practical exercises for a Compiler Design lab at JMS Institute of Technology, focusing on various aspects of compiler construction such as lexical analysis, syntax parsing, and NFA operations. It includes detailed aims, program codes, and outputs for tasks like designing a lexical analyzer, implementing YACC specifications, and converting NFA with ε transitions. Each practical exercise is structured with clear objectives and example code to facilitate understanding of compiler design concepts.

Uploaded by

daredevil19q
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)
3 views

CD Lab Manual

The document outlines practical exercises for a Compiler Design lab at JMS Institute of Technology, focusing on various aspects of compiler construction such as lexical analysis, syntax parsing, and NFA operations. It includes detailed aims, program codes, and outputs for tasks like designing a lexical analyzer, implementing YACC specifications, and converting NFA with ε transitions. Each practical exercise is structured with clear objectives and example code to facilitate understanding of compiler design concepts.

Uploaded by

daredevil19q
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/ 28

JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

Practical File
Compiler Design
(BCS-652)
DEPARTMENT OF COMPUTER SCIENCE & ENGINEERING

Submitted By: Submitted To:

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

DEPARTMENT OF COMPUTER SCIENCE & ENGINEERING


COMPILER DESIGN LAB (BCS-652)
INDEX
Practical
Practical Name Sign.
No.

Design and implement a lexical analyzer for given language


1. using C and the lexical analyzer should ignore redundant spaces,
tabs and new lines.

2. Implementation of Lexical Analyzer Using Lex Tool

3. Generate YACC Specification for Syntactic Categories.

4. Write program to find ε – closure of all states of any given NFA


with ε transition.

5. Write program to convert NFA with ε transition to NFA without


ε transition.

6. Write a program to convert NFA to DFA.

7. Construct a recursive descent parser for an expression.

8. Write a program to perform loop unrolling.

9. Write a program to perform constant propagation.

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

Practical – 1
Aim: Design and implement a lexical analyzer for given language using C and the lexical
analyzer should ignore redundant spaces, tabs and new lines.

Program Code:

#include <stdio.h>
#include <ctype.h>

void lexical_analyzer(char *input) {


char current_char;
int i = 0;

while ((current_char = input[i]) != '\0') {


if (isspace(current_char)) {
i++;
continue;
}

if (isalpha(current_char)) {
printf("Identifier: %c\n", current_char);
i++;
}
else if (isdigit(current_char)) {
printf("Number: %c\n", current_char);
i++;
}
else if (current_char == '+') {
printf("Operator: +\n");
i++;
}
else if (current_char == '-') {
printf("Operator: -\n");
i++;
}
else if (current_char == '*') {
printf("Operator: *\n");
i++;
}
else if (current_char == '/') {
printf("Operator: /\n");
i++;
}
else {
printf("Unknown character: %c\n", current_char);
i++;
}
}

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

int main() {
char input[] = "int a = 5 + 3;";
lexical_analyzer(input);
return 0;
}

Output:

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

Practical - 2

Aim: Implementation of Lexical Analyzer Using Lex Tool

The Lex tool helps automate the generation of lexical analyzers. In this task, we'll use Lex to
generate a lexical analyzer.

Before proceeding with the code, you need to have Lex (or Flex, a common alternative)
installed on your system.

Code:

1. Create the Lex file (e.g., lexer.l):

%{
#include <stdio.h>
#include <ctype.h>
%}

%%
[ \t\n]+ { /* Skip spaces, tabs, and newlines */ }
[0-9]+ { printf("Number: %s\n", yytext); }
[a-zA-Z]+ { printf("Identifier: %s\n", yytext); }
"+" { printf("Operator: +\n"); }
"-" { printf("Operator: -\n"); }
"*" { printf("Operator: *\n"); }
"/" { printf("Operator: /\n"); }
. { printf("Unknown character: %s\n", yytext); }
%%

int main() {
yylex(); // Start lexical analysis
return 0;
}

2. To Compile and Run:

lex lexer.l
gcc lex.yy.c -o lexer -ll
./lexer

Input:

echo "int a = 5 + 3;"

Output:

Identifier: int
Identifier: a

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

Operator: =
Number: 5
Operator: +
Number: 3
Unknown character: ;

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

Practical - 3

Aim: Generate YACC Specification for Syntactic Categories.

a) Program to Recognize a Valid Arithmetic Expression Using Operators +, -, * , and /.

Procedure:

1. Create the Lex file (e.g., lexer.l):

%{
#include "y.tab.h" // Include the YACC header
%}

%%
[0-9]+ { yylval = atoi(yytext); return NUMBER; }
[+\-*/] { return yytext[0]; } // Return operator as token
[ \t\n]+ { /* Skip spaces, tabs, and newlines */ }
%%

int yywrap() {
return 1;
}

2. Create the YACC file (e.g., parser.y):

%{
#include <stdio.h>
#include <stdlib.h>

int yylex(); // Declaration of the lexical analyzer


void yyerror(char *s) {
fprintf(stderr, "Error: %s\n", s);
}
%}

%union {
int num;
}

%token <num> NUMBER


%left '+' '-'
%left '*' '/'

%%
expr: expr '+' expr { printf("%d\n", $1 + $3); }
| expr '-' expr { printf("%d\n", $1 - $3); }
| expr '*' expr { printf("%d\n", $1 * $3); }

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

| expr '/' expr {


if ($3 == 0) {
yyerror("Division by zero");
YYABORT;
} else {
printf("%d\n", $1 / $3);
}
}
| NUMBER { printf("%d\n", $1); }
;
%%
int main() {
printf("Enter an arithmetic expression:\n");
yyparse(); // Start the parser
return 0;
}

3. To Compile and Run:

• First, generate the Lex and YACC files:

lex lexer.l
yacc -d parser.y

• Then, compile the generated C files:

gcc lex.yy.c y.tab.c -o calculator -ly -ll

• Run the program:

./calculator

Output:

Enter an arithmetic expression:


3 + 4 * 5
23

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

b) Program to Recognize a Valid Variable

A valid variable is defined as starting with a letter and followed by any number of letters or
digits. We can add a simple rule to Lex and YACC to handle this:

1. Lex file:

%{
#include "y.tab.h"
%}

%%
[a-zA-Z][a-zA-Z0-9]* { yylval = strdup(yytext); return VARIABLE; }
[0-9]+ { yylval = atoi(yytext); return NUMBER; }
[ \t\n]+ { /* Skip spaces */ }
%%

int yywrap() {
return 1;
}

2. YACC file:

%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int yylex();
void yyerror(char *s) {
fprintf(stderr, "Error: %s\n", s);
}

%}

%union {
char* str;
}

%token <str> VARIABLE


%token <num> NUMBER

%%
var: VARIABLE { printf("Valid Variable: %s\n", $1); }
| NUMBER { printf("Number: %d\n", $1); }
;
%%
int main() {
printf("Enter a variable or number:\n");

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

yyparse();
return 0;
}

3. To Compile and Run:

lex lexer.l
yacc -d parser.y
gcc lex.yy.c y.tab.c -o var_checker -ly -ll
./var_checker

Output Example:

Enter a variable or number:


myVariable123
Valid Variable: myVariable123

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

c. Implementation of a Calculator using Lex and YACC

Procedure:

1. Create the Lex file (lexer.l):

%{
#include "y.tab.h" // Include the YACC header for token definitions
%}

%%
[0-9]+ { yylval = atoi(yytext); return NUMBER; }
[+\-*/] { return yytext[0]; } // Return operator tokens
[ \t\n]+ { /* Skip spaces, tabs, and newlines */ }
%%

int yywrap() {
return 1;
}

2. Create the YACC file (parser.y):

%{
#include <stdio.h>
#include <stdlib.h>

int yylex(); // Forward declaration of lexical analyzer


void yyerror(char *s) {
fprintf(stderr, "Error: %s\n", s);
}
%}

%union {
int num;
}

%token <num> NUMBER


%left '+' '-'
%left '*' '/'
%right UMINUS

%%
expr: expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
| expr '*' expr { $$ = $1 * $3; }
| expr '/' expr {
if ($3 == 0) {
yyerror("Division by zero");
YYABORT;

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

} else {
$$ = $1 / $3;
}
}
| '(' expr ')' { $$ = $2; }
| '-' expr %prec UMINUS { $$ = -$2; }
| NUMBER { $$ = $1; }
;
%%
int main() {
printf("Enter an arithmetic expression:\n");
yyparse(); // Start parsing the input
return 0;
}

3. To Compile and Run:

lex lexer.l
yacc -d parser.y
gcc lex.yy.c y.tab.c -o calculator -ly -ll
./calculator

Output:

Enter an arithmetic expression:


(3 + 4) * 5
35

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

d. Convert BNF Rules into YACC Form and Write Code to Generate Abstract Syntax
Tree.

Procedure:

1. Create the Lex file (lexer.l):

%{
#include "y.tab.h"
%}

%%
[0-9]+ { yylval.num = atoi(yytext); return NUMBER; }
[+\-*/] { return yytext[0]; }
[ \t\n]+ { /* Skip spaces */ }
%%

int yywrap() {
return 1;
}

2. Create the YACC file (parser.y):

%{
#include <stdio.h>
#include <stdlib.h>

int yylex();
void yyerror(char *s) {
fprintf(stderr, "Error: %s\n", s);
}

struct ast {
int nodetype;
struct ast *left;
struct ast *right;
int value;
};

struct ast *new_ast_node(int nodetype, struct ast *left, struct ast *right, int value) {
struct ast *node = (struct ast *)malloc(sizeof(struct ast));
node->nodetype = nodetype;
node->left = left;
node->right = right;
node->value = value;
return node;
}

void print_ast(struct ast *node) {

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

if (!node) return;
if (node->left) print_ast(node->left);
if (node->right) print_ast(node->right);
printf("Node Type: %d, Value: %d\n", node->nodetype, node->value);
}
%}

%union {
int num;
struct ast *ast;
}

%token <num> NUMBER


%left '+' '-'
%left '*' '/'

%%
expr: expr '+' expr { $$ = new_ast_node('+', $1, $3, 0); }
| expr '-' expr { $$ = new_ast_node('-', $1, $3, 0); }
| expr '*' expr { $$ = new_ast_node('*', $1, $3, 0); }
| expr '/' expr { $$ = new_ast_node('/', $1, $3, 0); }
| '(' expr ')' { $$ = $2; }
| NUMBER { $$ = new_ast_node('N', NULL, NULL, $1); }
;

%%
int main() {
printf("Enter an arithmetic expression:\n");
yyparse();
return 0;
}

3. To Compile and Run:

lex lexer.l
yacc -d parser.y
gcc lex.yy.c y.tab.c -o ast_calculator -ly -ll
./ast_calculator

Output:

Enter an arithmetic expression:


(3 + 4) * 5
Node Type: 42, Value: 0
Node Type: 43, Value: 0
Node Type: N, Value: 3
Node Type: N, Value: 4

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

Practical – 4
Aim: Write program to find ε – closure of all states of any given NFA with ε transition.

#include <stdio.h>
#include <stdlib.h>

#define MAX_STATES 10
#define MAX_TRANSITIONS 10

// Structure for an NFA state and its transitions


struct nfa_state {
int state;
int epsilon[MAX_STATES];
int num_epsilon;
};

// Global variables
struct nfa_state nfa[MAX_STATES];
int nfa_size = 0;

// Function to find the epsilon closure of a state


void epsilon_closure(int state, int *closure) {
closure[state] = 1;

// Recursively add states reachable by epsilon transitions


for (int i = 0; i < nfa[state].num_epsilon; i++) {
int next_state = nfa[state].epsilon[i];
if (!closure[next_state]) {
epsilon_closure(next_state, closure);
}
}
}

// Function to add epsilon transition


void add_epsilon_transition(int from, int to) {
nfa[from].epsilon[nfa[from].num_epsilon++] = to;
}

int main() {
// Initialize NFA (for demonstration)
// Example: NFA with 4 states and some epsilon transitions
nfa_size = 4;

// Adding epsilon transitions


add_epsilon_transition(0, 1);
add_epsilon_transition(1, 2);

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

add_epsilon_transition(2, 3);

// Calculate epsilon-closure for each state


for (int i = 0; i < nfa_size; i++) {
int closure[MAX_STATES] = {0};
printf("Epsilon-closure for state %d: {", i);
epsilon_closure(i, closure);

// Print the epsilon-closure set


for (int j = 0; j < nfa_size; j++) {
if (closure[j]) {
printf("%d ", j);
}
}
printf("}\n");
}

return 0;
}

Output:

Epsilon-closure for state 0: {0 1 2 3 }


Epsilon-closure for state 1: {1 2 3 }
Epsilon-closure for state 2: {2 3 }
Epsilon-closure for state 3: {3 }

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

Program – 5

Aim: Write program to convert NFA with ε transition to NFA without ε transition.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_STATES 100


#define MAX_TRANSITIONS 100
#define MAX_EPSILON_TRANSITIONS 100

typedef struct {
int from;
int to;
} EpsilonTransition;

typedef struct {
int from;
char symbol;
int to;
} Transition;

EpsilonTransition epsilon_transitions[MAX_EPSILON_TRANSITIONS];
Transition transitions[MAX_TRANSITIONS];
int epsilon_count = 0;
int transition_count = 0;

// Function to add an epsilon transition


void add_epsilon_transition(int from, int to) {
epsilon_transitions[epsilon_count].from = from;
epsilon_transitions[epsilon_count].to = to;
epsilon_count++;
}

// Function to add a regular transition


void add_transition(int from, char symbol, int to) {
transitions[transition_count].from = from;
transitions[transition_count].symbol = symbol;
transitions[transition_count].to = to;
transition_count++;
}

// Function to compute the epsilon closure of a state


void epsilon_closure(int state, int *closure, int *closure_size) {
closure[(*closure_size)++] = state;

for (int i = 0; i < epsilon_count; i++) {


if (epsilon_transitions[i].from == state) {

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

int next_state = epsilon_transitions[i].to;


int found = 0;
for (int j = 0; j < *closure_size; j++) {
if (closure[j] == next_state) {
found = 1;
break;
}
}
if (!found) {
epsilon_closure(next_state, closure, closure_size);
}
}
}
}

// Function to convert NFA with epsilon transitions to NFA without epsilon transitions
void convert_nfa_with_epsilon_to_nfa() {
int nfa_without_epsilon[MAX_STATES][MAX_STATES] = {0}; // Adjacency matrix
for new NFA
int closure[MAX_STATES];
int closure_size;

for (int i = 0; i < MAX_STATES; i++) {


closure_size = 0;
epsilon_closure(i, closure, &closure_size);

for (int j = 0; j < closure_size; j++) {


for (int k = 0; k < transition_count; k++) {
if (transitions[k].from == closure[j]) {
int target_closure[MAX_STATES];
int target_closure_size = 0;
epsilon_closure(transitions[k].to, target_closure, &target_closure_size);

for (int l = 0; l < target_closure_size; l++) {


nfa_without_epsilon[closure[j]][target_closure[l]] = 1; // Mark transition
}
}
}
}
}

// Print the new NFA transitions


printf("NFA without ε transitions:\n");
for (int i = 0; i < MAX_STATES; i++) {
for (int j = 0; j < MAX_STATES; j++) {
if (nfa_without_epsilon[i][j]) {
printf("δ(%d, 'a') = %d\n", i, j); // Assuming 'a' for simplicity
}
}

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

}
}

int main() {
// Example NFA with ε transitions
add_epsilon_transition(0, 1);
add_epsilon_transition(1, 2);
add_epsilon_transition(2, 3);
add_epsilon_transition(1, 4);

// Example regular transitions


add_transition(0, 'a', 1);
add_transition(1, 'b', 2);
add_transition(2, 'c', 3);
add_transition(1, 'd', 4);

// Convert NFA with ε transitions to NFA without ε transitions


convert_nfa_with_epsilon_to_nfa();

return 0;
}

Output:

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

Program – 6

Aim: Write a program to convert NFA to DFA.

#include <stdio.h>
#include <string.h>

#define STATES 10
#define SYMBOLS 2

int nfa[STATES][SYMBOLS][STATES]; // Transition table for NFA


int dfa[100][SYMBOLS]; // Transition table for DFA
int dfa_states[100][STATES]; // DFA state combinations
int state_count = 0; // Count of DFA states

// Function to check if a state combination already exists in DFA states


int findStateCombination(int *state_combination, int n) {
for (int i = 0; i < state_count; i++) {
int match = 1;
for (int j = 0; j < n; j++) {
if (dfa_states[i][j] != state_combination[j]) {
match = 0;
break;
}
}
if (match)
return i;
}
return -1;
}

// Function to add a new state combination to DFA states


int addStateCombination(int *state_combination, int n) {
for (int i = 0; i < n; i++)
dfa_states[state_count][i] = state_combination[i];
return state_count++;
}

// Function to convert NFA to DFA


void convertNFAtoDFA(int n, int m) {
int queue[100][STATES], front = 0, rear = 0;
int initial_state[STATES] = {0};
initial_state[0] = 1; // Start state is q0

// Add the initial state to DFA


addStateCombination(initial_state, n);
memcpy(queue[rear++], initial_state, sizeof(initial_state));

while (front < rear) {

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

int current_state[STATES];
memcpy(current_state, queue[front++], sizeof(current_state));
int current_index = findStateCombination(current_state, n);

for (int j = 0; j < m; j++) {


int next_state[STATES] = {0};

// Calculate the next state for input symbol j


for (int i = 0; i < n; i++) {
if (current_state[i] == 1) {
for (int k = 0; k < n; k++) {
if (nfa[i][j][k] == 1)
next_state[k] = 1;
}
}
}

// Check if the next state already exists in DFA


int next_index = findStateCombination(next_state, n);
if (next_index == -1 && memcmp(next_state, (int[STATES]){0},
sizeof(next_state)) != 0) {
next_index = addStateCombination(next_state, n);
memcpy(queue[rear++], next_state, sizeof(next_state));
}

// Update DFA transition table


dfa[current_index][j] = next_index;
}
}
}

// Function to print DFA transition table


void printDFA(int n, int m) {
printf("\nDFA Transition Table:\n");
printf("State / Alphabet ");
for (int j = 0; j < m; j++)
printf("\t%c ", 'a' + j);
printf("\n");

for (int i = 0; i < state_count; i++) {


printf("{");
for (int j = 0; j < n; j++) {
if (dfa_states[i][j])
printf("q%d,", j);
}
printf("}\t");

for (int j = 0; j < m; j++) {


if (dfa[i][j] == -1) {

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

printf("\t{}");
} else {
printf("\t{");
for (int k = 0; k < n; k++) {
if (dfa_states[dfa[i][j]][k])
printf("q%d,", k);
}
printf("}");
}
}
printf("\n");
}
}

int main() {
int n, m;
printf("Enter number of states in NFA: ");
scanf("%d", &n);
printf("Enter number of input symbols: ");
scanf("%d", &m);

printf("Enter NFA transition table (1 if transition exists, 0 otherwise):\n");


for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
for (int k = 0; k < n; k++) {
scanf("%d", &nfa[i][j][k]);
}
}
}

// Initialize DFA transition table to -1


memset(dfa, -1, sizeof(dfa));

convertNFAtoDFA(n, m);
printDFA(n, m);
return 0;
}

Output:

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

Practical – 7

Aim: Construct a recursive descent parser for an expression.

Grammar:

Expression → Term { ('+' | '-') Term }


Term → Factor { ('*' | '/') Factor }
Factor → NUMBER | '(' Expression ')'
Code:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

const char* input;


char lookahead;

// Forward declarations
void expression();
void term();
void factor();
void match(char expected);

// Utility function to advance the lookahead


void nextToken() {
while (*input == ' ') input++; // skip whitespaces
lookahead = *input;
}

// Match and consume expected character


void match(char expected) {
if (lookahead == expected) {
input++;
nextToken();
} else {
printf("Syntax Error: Expected '%c', found '%c'\n", expected, lookahead);
exit(1);
}
}
// Parsing rules
void expression() {
term();
while (lookahead == '+' || lookahead == '-') {
char op = lookahead;
match(op);
term();

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

printf(" %c ", op); // postfix notation


}
}
void term() {
factor();
while (lookahead == '*' || lookahead == '/') {
char op = lookahead;
match(op);
factor();
printf(" %c ", op); // postfix notation
}
}

void factor() {
if (isdigit(lookahead)) {
printf(" %c ", lookahead); // number output
match(lookahead);
} else if (lookahead == '(') {
match('(');
expression();
match(')');
} else {
printf("Syntax Error: Unexpected character '%c'\n", lookahead);
exit(1);
}
}

int main() {
// Example input
input = "3+(4*5)-6";
nextToken(); // initialize lookahead

printf("Postfix: ");
expression();

if (lookahead != '\0') {
printf("\nSyntax Error: Unexpected characters at end of input\n");
return 1;
}
printf("\nParsing successful.\n");
return 0;
}

Output:

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

Practical – 8

Aim: Write a program to perform loop unrolling.

Loop unrolling is a compiler optimization technique where the number of iterations in a loop
is decreased by executing multiple operations per iteration. This reduces loop overhead and
can improve performance, especially in compute-intensive operations.

Code:

#include <stdio.h>
#include <time.h>

#define SIZE 1000000

// Function to sum array using a normal loop


int normal_sum(int arr[], int size) {
int sum = 0;
for (int i = 0; i < size; i++) {
sum += arr[i];
}
return sum;
}

// Function to sum array using loop unrolling (4 times)


int unrolled_sum(int arr[], int size) {
int sum = 0;
int i;

// Process 4 elements per iteration


for (i = 0; i <= size - 4; i += 4) {
sum += arr[i] + arr[i+1] + arr[i+2] + arr[i+3];
}

// Handle remaining elements (if size not a multiple of 4)


for (; i < size; i++) {
sum += arr[i];
}

return sum;
}

int main() {
int arr[SIZE];

// Initialize array with values 1 to SIZE


for (int i = 0; i < SIZE; i++) {
arr[i] = 1; // or any pattern
}

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

clock_t start, end;

// Measure time for normal loop


start = clock();
int sum1 = normal_sum(arr, SIZE);
end = clock();
printf("Normal Sum = %d, Time = %lf seconds\n", sum1, (double)(end - start) /
CLOCKS_PER_SEC);

// Measure time for unrolled loop


start = clock();
int sum2 = unrolled_sum(arr, SIZE);
end = clock();
printf("Unrolled Sum = %d, Time = %lf seconds\n", sum2, (double)(end - start) /
CLOCKS_PER_SEC);

return 0;
}

Output:

Compiler Design Lab (BCS-652)


JMS Institute of Technology, Ghaziabad Department of Computer Science & Engineering

Practical – 9

Aim: Write a program to perform constant propagation.

Constant Propagation is a compiler optimization technique where known constant values are
substituted into expressions at compile time. In C, this is typically handled by the compiler
itself.

Code:

#include <stdio.h>

// Original code without constant propagation


void without_constant_propagation() {
int a = 5;
int b = 10;
int c = a + b; // Expression involves variables
int d = c * 2;

printf("Without Constant Propagation: d = %d\n", d);


}

// Optimized version with constant propagation


void with_constant_propagation() {
// The compiler or programmer realizes:
// a = 5, b = 10 → c = 15 → d = 30
int d = 30;

printf("With Constant Propagation: d = %d\n", d);


}

int main() {
without_constant_propagation();
with_constant_propagation();
return 0;
}

Output:

Compiler Design Lab (BCS-652)

You might also like