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

A3_47_Practical6

Uploaded by

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

A3_47_Practical6

Uploaded by

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

Shri Ramdeobaba College of Engineering and Management, Nagpur

Department of Computer Science and Engineering


Session: 2024-2025
Compiler Design Lab

PRACTICAL No. 6
Topic: Code Optimization
Aim: Write a code to implement local optimization techniques until no further optimization is
possible for the given three address code.
Input: Three Address Code (non-optimized)

Original Three Address Code:

0: t0 = 4

1: t1 = 2

2: t2 = 4

3: t0 = 3 + t4

4: t1 = 3 - t2

5: t1 = 4 - 2

6: t0 = t2

7: t2 = 5 + t3

8: t3 = 9 / t4

9: t2 = 7 * 8

10: t0 = 3 / 4

11: t1 = t4 / 9

12: t0 = 2 / 9

13: t3 = 10 * 2

14: t4 = t3

Implementation: Identify and apply local optimization techniques to optimize the TAC

 Copy Propagation
 Constant propagation
 Constant Folding
 Common Subexpression Elimination
 Dead code elimination

Code:

import random
import re

from collections import defaultdict

class ThreeAddressCode:

def __init__(self):

self.statements = []

self.variable_map = {} # For copy propagation

self.constant_map = {} # For constant propagation

self.expression_map = {} # For common subexpression elimination

self.used_variables = set() # For dead code elimination

self.defined_variables = set() # For dead code elimination

def add_statement(self, statement):

"""Add a statement to the three address code."""

self.statements.append(statement)

def generate_random_code(self, num_statements=15, num_variables=5):

"""Generate random three address code."""

operations = ['+', '-', '*', '/']

variables = [f't{i}' for i in range(num_variables)]

constants = list(range(1, 11))

# Generate initial assignments with constants to some variables

for i in range(min(num_variables, 3)):

var = variables[i]

const = random.choice(constants)

self.add_statement(f"{var} = {const}")

# Generate the rest of the statements


for _ in range(num_statements - min(num_variables, 3)):

result = random.choice(variables)

# Decide if it's a binary operation or a copy

if random.random() < 0.8: # 80% chance for binary operation

op = random.choice(operations)

# Choose operands (variables or constants)

operand1 = random.choice(variables + [str(c) for c in constants])

operand2 = random.choice(variables + [str(c) for c in constants])

self.add_statement(f"{result} = {operand1} {op} {operand2}")

else: # 20% chance for a copy

source = random.choice(variables)

if source != result: # Avoid self-assignment

self.add_statement(f"{result} = {source}")

return self.statements

def analyze_code(self):

"""Analyze the code to prepare for optimizations."""

self.variable_map = {}

self.constant_map = {}

self.expression_map = {}

self.used_variables = set()

self.defined_variables = set()

# First pass: collect defined variables

for stmt in self.statements:


parts = stmt.split('=')

if len(parts) == 2:

target = parts[0].strip()

self.defined_variables.add(target)

# Second pass: collect used variables and build maps

for i, stmt in enumerate(self.statements):

if '=' not in stmt:

continue

target, expression = [part.strip() for part in stmt.split('=', 1)]

# For copy propagation (x = y)

if re.match(r'^\w+$', expression):

self.variable_map[target] = expression

# For constant propagation (x = constant)

if re.match(r'^\d+$', expression):

self.constant_map[target] = int(expression)

# For common subexpression elimination

tokens = re.findall(r'[+\-*/]|\w+|\d+', expression)

if len(tokens) == 3 and tokens[1] in ['+', '-', '*', '/']:

expr_key = f"{tokens[0]} {tokens[1]} {tokens[2]}"

if expr_key not in self.expression_map:

self.expression_map[expr_key] = target

# Collect used variables

for token in re.findall(r'\b[a-zA-Z]\w*\b', expression):


self.used_variables.add(token)

def copy_propagation(self):

"""Perform copy propagation optimization."""

modified = False

for i, stmt in enumerate(self.statements):

if '=' not in stmt:

continue

target, expression = [part.strip() for part in stmt.split('=', 1)]

# Replace variables with their copies

for var, val in self.variable_map.items():

if var != target: # Avoid cycles

pattern = r'\b' + re.escape(var) + r'\b'

new_expr = re.sub(pattern, val, expression)

if new_expr != expression:

self.statements[i] = f"{target} = {new_expr}"

modified = True

expression = new_expr

return modified

def constant_propagation(self):

"""Perform constant propagation optimization."""

modified = False

for i, stmt in enumerate(self.statements):

if '=' not in stmt:

continue
target, expression = [part.strip() for part in stmt.split('=', 1)]

# Replace variables with their constant values

for var, val in self.constant_map.items():

if var != target: # Avoid cycles

pattern = r'\b' + re.escape(var) + r'\b'

new_expr = re.sub(pattern, str(val), expression)

if new_expr != expression:

self.statements[i] = f"{target} = {new_expr}"

modified = True

expression = new_expr

return modified

def constant_folding(self):

"""Perform constant folding optimization."""

modified = False

for i, stmt in enumerate(self.statements):

if '=' not in stmt:

continue

target, expression = [part.strip() for part in stmt.split('=', 1)]

# Find expressions with constants only

# Match patterns like "2 + 3", "5 * 7", etc.

match = re.search(r'(\d+)\s*([+\-*/])\s*(\d+)', expression)

if match:

operand1 = int(match.group(1))
operator = match.group(2)

operand2 = int(match.group(3))

# Compute the result

result = None

if operator == '+':

result = operand1 + operand2

elif operator == '-':

result = operand1 - operand2

elif operator == '*':

result = operand1 * operand2

elif operator == '/' and operand2 != 0:

result = operand1 // operand2 # Integer division

if result is not None:

# Replace the expression with the computed constant

new_expr = expression.replace(match.group(0), str(result))

self.statements[i] = f"{target} = {new_expr}"

# If the entire right side is now a constant, update constant_map

if new_expr.isdigit():

self.constant_map[target] = int(new_expr)

modified = True

return modified

def common_subexpression_elimination(self):

"""Perform common subexpression elimination."""


modified = False

for i, stmt in enumerate(self.statements):

if '=' not in stmt:

continue

target, expression = [part.strip() for part in stmt.split('=', 1)]

# Check if this is a binary operation

tokens = re.findall(r'[+\-*/]|\w+|\d+', expression)

if len(tokens) == 3 and tokens[1] in ['+', '-', '*', '/']:

expr_key = f"{tokens[0]} {tokens[1]} {tokens[2]}"

# If we've seen this expression before, replace it

if expr_key in self.expression_map and self.expression_map[expr_key] != target:

self.statements[i] = f"{target} = {self.expression_map[expr_key]}"

modified = True

# Add mapping for copy propagation

self.variable_map[target] = self.expression_map[expr_key]

else:

# Otherwise, record this expression

self.expression_map[expr_key] = target

return modified

def dead_code_elimination(self):

"""Perform dead code elimination."""

modified = False

# First, update the analysis

self.analyze_code()
# Find variables that are defined but never used

unused_vars = self.defined_variables - self.used_variables

# Remove statements that assign to unused variables

i=0

while i < len(self.statements):

stmt = self.statements[i]

if '=' in stmt:

target = stmt.split('=')[0].strip()

if target in unused_vars and not re.search(r'\b' + re.escape(target) + r'\b', stmt.split('=')


[1]):

self.statements.pop(i)

modified = True

continue

i += 1

return modified

def optimize(self):

"""Apply all optimization techniques until no further optimization is possible."""

print("Original Three Address Code:")

self.print_code()

iteration = 1

while True:

self.analyze_code()

# Apply each optimization technique


cp_mod = self.copy_propagation()

const_prop_mod = self.constant_propagation()

const_fold_mod = self.constant_folding()

cse_mod = self.common_subexpression_elimination()

dce_mod = self.dead_code_elimination()

# Check if any modifications were made

if cp_mod or const_prop_mod or const_fold_mod or cse_mod or dce_mod:

print(f"\nAfter Iteration {iteration}:")

self.print_code()

iteration += 1

else:

break

print("\nFinal Optimized Three Address Code:")

self.print_code()

def print_code(self):

"""Print the current three address code."""

for i, stmt in enumerate(self.statements):

print(f"{i}: {stmt}")

def main():

tac = ThreeAddressCode()

# Option 1: Generate random TAC

tac.generate_random_code(num_statements=15, num_variables=5)

# Option 2: Use a predefined example (uncomment to use)


"""

tac.add_statement("a = 3")

tac.add_statement("b = 4")

tac.add_statement("c = a + b") # c = 7

tac.add_statement("d = b") # copy of b

tac.add_statement("e = c + d") # CSE opportunity

tac.add_statement("f = a + b") # CSE opportunity (same as c)

tac.add_statement("g = 2 * f") # propagation opportunity

tac.add_statement("h = 3 + 4") # constant folding opportunity (h = 7)

tac.add_statement("i = h") # copy of h

tac.add_statement("j = 10") # dead code (j is never used)

"""

# Apply optimizations

tac.optimize()

if __name__ == "__main__":

main()

Output: Optimized Three Address Code

After Iteration 1:

0: t0 = 4

1: t0 = 3 + t3

2: t0 = 4

3: t3 = 9 / t3

4: t0 = 0

5: t0 = 0

6: t3 = 20
After Iteration 2:

0: t3 = 9 / t3

1: t3 = 20

Final Optimized Three Address Code:

0: t3 = 9 / t3

1: t3 = 20

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