Commit 69316316 authored by Taddeus Kroes's avatar Taddeus Kroes

Added latest optimizations.

parent 8b0656ec
......@@ -5,31 +5,11 @@ from src.liveness import RESERVED_REGISTERS, is_reg_dead_after
from src.dataflow import succ
#def reg_can_be_used_in(reg, block, start, end):
# """Check if a register addres safely be used in a block section using local
# dataflow analysis."""
# # Check if the register used or defined in the block section
# for s in block[start:end]:
# if s.uses(reg) or s.defines(reg):
# return False
#
# # Check if the register is used inside the block after the specified
# # section, without having been re-assigned first
# for s in block[end:]:
# if s.uses(reg):
# return False
# elif s.defines(reg):
# return True
#
# return reg not in block.live_out
def find_free_reg(block, start):
"""Find a temporary register that is free in a given list of statements."""
for i in xrange(8, 16):
tmp = '$%d' % i
#if reg_can_be_used_in(tmp, block, start, end):
if is_reg_dead_after(tmp, block, start):
return tmp
......@@ -53,54 +33,88 @@ def eliminate_common_subexpressions(block):
occurrences to a move instruction from that address.
"""
changed = False
prev = False
block.reset()
while not block.end():
s = block.read()
args = s[1:]
mult = False
if s.is_command('mflo') and prev and prev.name == 'mult':
mult = prev
args = mult.args
elif not s.is_arith():
prev = s
continue
if s.is_arith():
pointer = block.pointer
occurrences = [pointer - 1]
args = s[1:]
# Collect similar statements
while not block.end():
s2 = block.read()
if not s2.is_command():
continue
# Stop if one of the arguments is assigned
if len(s2) and s2[0] in args:
break
pointer = block.pointer
occurrences = [pointer - 1]
# Replace a similar expression by a move instruction
if s2.name == s.name and s2[1:] == args:
occurrences.append(block.pointer - 1)
# Collect similar statements
while not block.end():
s2 = block.read()
if len(occurrences) > 1:
new_reg = find_free_reg(block, occurrences[0])
if not s2.is_command():
continue
# Replace all occurrences with a move statement
message = 'Common subexpression reference: %s %s' \
% (s.name, ','.join(map(str, [new_reg] + s[1:])))
# Stop if one of the arguments is assigned
assign = False
for occurrence in occurrences:
rd = block[occurrence][0]
block.replace(1, [S('command', 'move', rd, new_reg)], \
start=occurrence, message=message)
for reg in s2.get_def():
if reg in args:
assign = True
break
# Insert the calculation before the original with the new
# destination address
if assign:
break
# Replace a similar expression by a move instruction
if mult:
# Multiplication has two instructions: mult and mflo
if s2.name == 'mult' and s2.args == args:
mflo = block.peek()
if mflo.is_command('mflo'):
occurrences.append(block.pointer - 1)
elif s2.name == s.name and s2[1:] == args:
# Regular arithmetic command
occurrences.append(block.pointer - 1)
if len(occurrences) > 1:
new_reg = find_free_reg(block, occurrences[0])
# Replace each occurrence 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, message=message)
# Insert the calculation before the original with the new
# destination address
if mult:
message = 'Common subexpression: mult ' \
+ ','.join(map(str, args))
block.insert(S('command', 'mult', *args), \
index=occurrences[0], message=message)
block.insert(S('command', 'mflo', new_reg), \
index=occurrences[0], message=' |')
else:
message = 'Common subexpression: %s %s' \
% (s.name, ','.join(map(str, s)))
block.insert(S('command', s.name, *([new_reg] + args)), \
index=occurrences[0], message=message)
changed = True
index=occurrences[0], message=message)
changed = True
prev = s
# Reset pointer to continue from the original statement
block.pointer = pointer
# Reset pointer to continue from the original statement
block.pointer = pointer
return changed
......@@ -473,26 +487,26 @@ def propagate_copies(block):
# Determine uses of x in successors of the block
# Determine if for each of those uses if this is the only
# definition reaching it -> s in in[B_use]
#if s.sid in block.reach_out:
# for b in filter(lambda b: (x, y) in b.copy_in, succ(block)):
# print b
# for s2 in b:
# # Determine if for each of those uses this is the only
# # definition reaching it -> s in in[B_use]
# i = s2.uses(x, True)
# if i != -1:
# s2.replace_usage(x, y, i, block.bid)
# print ' Replaced %s with %s from block %d' \
# % (x, y, block.bid)
# changed = True
# # An assignment to x or y kills the copy statement x =
# # y
# defined = s2.get_def()
# if x in defined or y in defined:
# break
if s.sid in block.reach_out:
for b in filter(lambda b: (x, y) in b.copy_in, succ(block)):
print b
for s2 in b:
# Determine if for each of those uses this is the only
# definition reaching it -> s in in[B_use]
i = s2.uses(x, True)
if i != -1:
s2.replace_usage(x, y, i, block.bid)
print ' Replaced %s with %s from block %d' \
% (x, y, block.bid)
changed = True
# An assignment to x or y kills the copy statement x =
# y
defined = s2.get_def()
if x in defined or y in defined:
break
return changed
......
from copy import copy
import re
......@@ -7,7 +8,7 @@ class Statement:
def __init__(self, stype, name, *args, **kwargs):
self.stype = stype
self.name = name
self.args = list(args)
self.args = copy(list(args))
self.options = kwargs
# Assign a unique ID to each statement
......@@ -96,10 +97,10 @@ class Statement:
's.s', 's.b']
def is_arith(self):
"""Check if the statement is an arithmetic operation."""
"""Check if the statement is an aritmethic operation."""
return self.is_command() \
and re.match('^s(ll|rl|ra)'
+ '|(mfhi|mflo|abs|neg|and|[xn]?or)'
+ '|(abs|neg|and|[xn]?or)'
+ '|(add|sub|slt)u?'
+ '|(add|sub|mult|div|abs|neg|sqrt|c)\.[sd]$', \
self.name)
......@@ -252,7 +253,7 @@ class Statement:
return reg in use
def replace_usage(self, x, y, index, bid=0):
"""Replace the uses of register x by y."""
"""Replace uses of register x by y at the specified index."""
self[index] = re.sub('\\' + x + '(?!\d)', y, str(self[index]))
if bid:
......
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