Commit f7e3d0c6 authored by Taddeus Kroes's avatar Taddeus Kroes

Implemented constant folding.

parent d890c575
...@@ -65,43 +65,90 @@ def to_hex(value): ...@@ -65,43 +65,90 @@ def to_hex(value):
def fold_constants(block): def fold_constants(block):
""" """
Constant folding: Constant folding:
- An immidiate load defines a register value:
li $reg, XX -> register[$reg] = XX
- Integer variable definition is of the following form: - Integer variable definition is of the following form:
li $reg, XX li $reg, XX -> constants[VAR] = XX
sw $reg, VAR sw $reg, VAR -> register[$reg] = XX
save this as:
reg[$reg] = XX
constants[VAR] = XX
- When a variable is used, the following happens: - When a variable is used, the following happens:
lw $reg, VAR lw $reg, VAR -> register[$reg] = constants[VAR]
save this as:
reg[$reg] = constants[VAR]
""" """
found = False
# Variable values
constants = {} constants = {}
reg = {}
# Current known values in register
register = {}
while not block.end(): while not block.end():
s = block.read() s = block.read()
if s.is_load(): if not s.is_command():
constants[s[0]] = s[1] continue
elif s.is_command() and len(s) == 3:
d, s, t = s if s.name == 'li':
# Save value in register
register[s[0]] = int(s[1], 16)
elif s.name == 'move' and s[0] in register:
reg_to, reg_from = s
if reg_from in register:
# Other value is also known, copy its value
register[reg_to] = register[reg_to]
else:
# Other value is unknown, delete the value
del register[reg_to]
elif s.name == 'sw' and s[0] in register:
# Constant variable definition, e.g. 'int a = 1;'
constants[s[1]] = register[s[0]]
elif s.name == 'lw' and s[1] in constants:
# Usage of variable with constant value
register[s[0]] = constants[s[1]]
elif s.name in ['addu', 'subu', 'mult', 'div']:
# Calculation with constants
rd, rs, rt = s
rs_known = rs in register
rt_known = rt in register
if rs_known and rt_known:
# a = 5 -> b = 15
# c = 10
# b = a + c
rs_val = register[rs]
rt_val = register[rt]
if s in constants and t in constants:
if s.name == 'addu': if s.name == 'addu':
result = s + t result = to_hex(rs_val + rt_val)
elif s.name == 'subu':
result = s - t
elif s.name == 'mult':
result = s * t
elif s.name == 'div':
result = s / t
block.replace(1, [S('command', 'li', to_hex(result))])
constants[d] = result
#else:
return False if s.name == 'subu':
result = to_hex(rs_val - rt_val)
if s.name == 'mult':
result = to_hex(rs_val * rt_val)
if s.name == 'div':
result = to_hex(rs_val / rt_val)
block.replace(1, [S('command', 'li', result)])
register[rd] = result
found = True
elif rt_known:
# c = 10 -> b = a + 10
# b = c + a
s[2] = register[rt]
found = True
elif rs_known and s.name in ['addu', 'mult']:
# a = 10 -> b = c + 10
# b = c + a
s[1] = rt
s[2] = register[rs]
found = True
elif len(s) and s[0] in register:
# Known register is overwritten, remove its value
del register[s[0]]
return found
def copy_propagation(block): def copy_propagation(block):
......
import unittest import unittest
from src.optimize.advanced import eliminate_common_subexpressions from src.optimize.advanced import eliminate_common_subexpressions, \
fold_constants, copy_propagation
from src.statement import Statement as S, Block as B from src.statement import Statement as S, Block as B
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment