| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- from src.statement import Statement as S
- def create_variable():
- return '$15'
- def eliminate_common_subexpressions(block):
- """
- Common subexpression elimination:
- - Traverse through the statements in reverse order.
- - If the statement can be possibly be eliminated, walk further collecting
- all other occurrences of the expression until one of the arguments is
- assigned in a statement, or the start of the block has been reached.
- - If one or more occurrences were found, insert the expression with a new
- destination address before the last found occurrence and change all
- occurrences to a move instruction from that address.
- """
- found = False
- block.reverse_statements()
- while not block.end():
- s = block.read()
- if s.is_arith():
- pointer = block.pointer
- last = False
- new_reg = False
- args = s[1:]
- # Collect similar statements
- while not block.end():
- s2 = block.read()
- # 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
- if s2.name == s.name and s2[1:] == args:
- if not new_reg:
- new_reg = create_variable()
- block.replace(1, [S('command', 'move', s2[0], new_reg)])
- last = block.pointer
- # Insert an additional expression with a new destination address
- if last:
- block.insert(S('command', s.name, [new_reg] + args), last)
- found = True
- # Reset pointer to and continue from the original statement
- block.pointer = pointer
- block.reverse_statements()
- return found
- def to_hex(value):
- """Create the hexadecimal string of an integer."""
- return '0x%08x' % value
- def fold_constants(block):
- """
- Constant folding:
- - An immidiate load defines a register value:
- li $reg, XX -> register[$reg] = XX
- - Integer variable definition is of the following form:
- li $reg, XX -> constants[VAR] = XX
- sw $reg, VAR -> register[$reg] = XX
- - When a variable is used, the following happens:
- lw $reg, VAR -> register[$reg] = constants[VAR]
- """
- found = False
- # Variable values
- constants = {}
- # Current known values in register
- register = {}
- while not block.end():
- s = block.read()
- if not s.is_command():
- continue
- 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.name == 'addu':
- result = to_hex(rs_val + rt_val)
- 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):
- """
- Rename values that were copied to there original, so the copy statement
- might be useless, allowing it to be removed by dead code elimination.
- """
- moves_from = []
- moves_to = []
- while not block.end():
- s = block.read()
-
- if len(s) == 3:
- print "s[0] = ", s[0]
- print "s[1] = ", s[1]
- print "s[2] = ", s[2]
-
- if moves_from:
- print "fr: ", moves_from
- print "to: ", moves_to
- if s.is_command('move') and s[0] not in moves_to:
- moves_from.append(s[1])
- moves_to.append(s[0])
- print "Added move to list."
- elif s.is_command('move'):
- for i in xrange(len(moves_to)):
- if moves_to[i] == s[0]:
- moves_from[i] = s[1]
- elif len(s) == 3 and s[0] in moves_to:
- print len(s)
- print len(moves_to)
- for i in xrange(len(moves_to)):
- if moves_to[i] == s[0]:
- del moves_to[i]
- del moves_from[i]
- "Removed move from list."
- elif len(s) == 3 and (s[1] in moves_to or s[2] in moves_to):
- print "Have to propagate."
- for i in xrange(len(moves_to)):
- if s[1] == moves_to[i]:
- s[1] = moves_from[i]
- print "Propagated"
-
- if s[2] == moves_to[i]:
- s[2] = moves_from[i]
- print "Propagated"
-
- print ""
- return False
|