Skip to content
Snippets Groups Projects
Commit 69316316 authored by Taddeus Kroes's avatar Taddeus Kroes
Browse files

Added latest optimizations.

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