Commit 555624cb authored by Taddeus Kroes's avatar Taddeus Kroes

Tested constant folding and added some replacement messages.

parent 50c79cdf
......@@ -79,15 +79,20 @@ def eliminate_common_subexpressions(block):
new_reg = find_free_reg(block, occurrences[0], occurrences[-1])
# Replace all occurrences with a move statement
message = 'Common subexpression reference: %s %s' \
% (s.name, ', '.join(map(str, [new_reg] + s[1:])))
for occurrence in occurrences:
rd = block[occurrence][0]
block.replace(1, [S('command', 'move', rd, new_reg)], \
start=occurrence)
start=occurrence, message=message)
# Insert the calculation before the original with the new
# destination address
message = 'Common subexpression: %s %s' \
% (s.name, ', '.join(map(str, s)))
block.insert(S('command', s.name, *([new_reg] + args)), \
index=occurrences[0])
index=occurrences[0], message=message)
changed = True
......@@ -129,6 +134,7 @@ def fold_constants(block):
while not block.end():
s = block.read()
known = []
if not s.is_command():
continue
......@@ -136,27 +142,34 @@ def fold_constants(block):
if s.name == 'li':
# Save value in register
register[s[0]] = int(s[1], 16)
known.append((s[0], register[s[0]]))
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_from]
known.append((reg_to, register[reg_to]))
else:
# Other value is unknown, delete the value
del register[reg_to]
known.append((reg_to, 'unknown'))
elif s.name == 'sw' and s[0] in register:
# Constant variable definition, e.g. 'int a = 1;'
constants[s[1]] = register[s[0]]
known.append((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]]
known.append((s[0], register[s[0]]))
elif s.name == 'mflo' and '$lo' in register:
# Move of `Lo' register to another register
register[s[0]] = register['$lo']
known.append((s[0], register[s[0]]))
elif s.name == 'mfhi' and '$hi' in register:
# Move of `Hi' register to another register
register[s[0]] = register['$hi']
known.append((s[0], register[s[0]]))
elif s.name in ['mult', 'div'] \
and s[0]in register and s[1] in register:
# Multiplication/division with constants
......@@ -167,51 +180,68 @@ def fold_constants(block):
if not a or not b:
# Multiplication by 0
hi = lo = to_hex(0)
message = 'Multiplication by 0: %d * 0' % (b if a else a)
elif a == 1:
# Multiplication by 1
hi = to_hex(0)
lo = to_hex(b)
message = 'Multiplication by 1: %d * 1' % b
elif b == 1:
# Multiplication by 1
hi = to_hex(0)
lo = to_hex(a)
message = 'Multiplication by 1: %d * 1' % a
else:
# Calculate result and fill Hi/Lo registers
binary = bin(a * b)[2:]
result = a * b
binary = bin(result)[2:]
binary = '0' * (64 - len(binary)) + binary
hi = int(binary[:32], base=2)
lo = int(binary[32:], base=2)
message = 'Constant multiplication: %d * %d = %d' \
% (a, b, result)
# Replace the multiplication with two immidiate loads to the
# Hi/Lo registers
block.replace(1, [S('command', 'li', '$hi', hi),
S('command', 'li', '$lo', li)])
S('command', 'li', '$lo', li)],
message=message)
elif s.name == 'div':
lo, hi = divmod(rs, rt)
register['$lo'], register['$hi'] = lo, hi
known += [('$lo', lo), ('$hi', hi)]
changed = True
elif s.name in ['addu', 'subu']:
# Addition/subtraction with constants
rd, rs, rt = s
rs_known = rs in register
rt_known = rt in register
print 'rs:', rs, type(rs)
print 'rt:', rt, type(rt)
if rs_known and rt_known:
if (rs_known or isinstance(rs, int)) and \
(rt_known or isinstance(rt, int)):
# a = 5 -> b = 15
# c = 10
# b = a + c
rs_val = register[rs]
rt_val = register[rt]
rs_val = register[rs] if rs_known else rs
rt_val = register[rt] if rt_known else rt
if s.name == 'addu':
result = to_hex(rs_val + rt_val)
result = rs_val + rt_val
message = 'Constant addition: %d + %d = %d' \
% (rs_val, rt_val, result)
if s.name == 'subu':
result = to_hex(rs_val - rt_val)
result = rs_val - rt_val
message = 'Constant subtraction: %d - %d = %d' \
% (rs_val, rt_val, result)
block.replace(1, [S('command', 'li', rd, result)])
block.replace(1, [S('command', 'li', rd, to_hex(result))],
message=message)
register[rd] = result
known.append((rd, result))
changed = True
continue
......@@ -228,13 +258,20 @@ def fold_constants(block):
changed = True
if s[2] == 0:
# Addition/subtraction with 0
block.replace(1, [S('command', 'move', rd, s[1])])
# Addition/subtraction by 0
message = '%s by 0: %s * 1' % ('Addition' if s.name == 'addu' \
else 'Substraction', s[1])
block.replace(1, [S('command', 'move', rd, s[1])], \
message=message)
else:
for reg in s.get_def():
if reg in register:
# Known register is overwritten, remove its value
del register[reg]
known.append((reg, 'unknown'))
if block.debug and len(known):
s.set_inline_comment(','.join([' %s = %s' % k for k in known]))
return changed
......
......@@ -47,6 +47,7 @@ def t_offset_address(t):
def t_int(t):
r'-?[0-9]+'
t.type = 'WORD'
t.value = int(t.value)
return t
def t_WORD(t):
......
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