| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- from utils import Statement as S, find_basic_blocks
- def optimize_branch_jump_label(statements):
- """Optimize jumps after branches."""
- out_statements = []
- for i in xrange(len(statements)):
- if i + 3 > len(statements):
- out_statements.append(statements[i])
- continue
- stype, name, args = statements[i]
- stype2, name2, args2 = statements[i + 1]
- stype3, name3, args3 = statements[i + 2]
- if stype == 'command' and name == 'beq' and \
- stype2 == 'command' and name2 in ['j', 'jal'] and \
- stype3 == 'label' and name3 == args['args'][2]:
- out_statements.append(('command', 'bne', \
- {'args': [args['args'][0], args['args'][1], args2['args'][0]]}))
- out_statements.append(statements[1 + 2])
- i += 3
- else:
- out_statements.append(statements[i])
- return out_statements
- def optimize_global(statements):
- """Optimize one-line statements in entire code."""
- old_len = -1
- while old_len != len(statements):
- old_len = len(statements)
- while not statements.end():
- s = statements.read()
- # mov $regA,$regB -> --- remove it
- if s.is_command() and s.name == 'move' and s[0] == s[1]:
- statements.replace(1, [])
- # mov $regA,$regB -> instr $regA, $regB, ...
- # instr $regA, $regA, ...
- if s.is_command() and s.name == 'move':
- ins = statements.peek()
- if ins and len(ins) >= 2 and ins[0] == s[0] and ins[1] == s[0]:
- ins[1] = s[1]
- # instr $regA, ... -> instr $4, ...
- # mov $4, $regA jal XX
- # jal XX
- if s.is_command() and len(s):
- following = statements.peek(2)
- if len(following) == 2:
- mov, jal = following
- if mov.name == 'move' and mov[1] == s[0] \
- and jal.name == 'jal':
- s[0] = mov[0]
- statements.replace(1, [], start=statements.pointer + 1)
- # sw $regA, XX -> sw $regA, XX
- # ld $regA, XX
- # shift $regA, $regA, 0 -> --- remove it
- if s.is_shift() and s[0] == s[1] and s[2] == 0:
- statements.replace(1, [])
- # add $regA, $regA, X -> lw ..., X($regA)
- # lw ..., 0($regA)
- # beq ..., $Lx -> bne ..., $Ly
- # j $Ly $Lx:
- # $Lx:
- #if block.peek(3):
- # block.replace(3, [nieuwe statements])
- return statements
- def optimize_blocks(blocks):
- """Call the optimizer for each basic block. Do this several times until
- no more optimizations are achieved."""
- changed = True
- while changed:
- changed = False
- optimized = []
- for block in blocks:
- block_changed, b = optimize_block(block)
- optimized.append(b)
- if block_changed:
- changed = True
- blocks = optimized
- return reduce(lambda a, b: a + b, blocks, [])
- def optimize_block(statements):
- """Optimize a basic block."""
- changed = False
- output_statements = []
- for statement in statements:
- new_statement = statement
- output_statements.append(new_statement)
- return changed, output_statements
- def optimize(original, verbose=0):
- """optimization wrapper function, calls global and basic-block level
- optimization functions."""
- # Optimize on a global level
- opt_global = optimize_global(original)
- # Optimize basic blocks
- basic_blocks = find_basic_blocks(opt_global)
- blocks = optimize_blocks(basic_blocks)
- opt_blocks = reduce(lambda a, b: a.statements + b.statements, blocks)
- if verbose:
- o = len(original)
- g = len(opt_global)
- b = len(opt_blocks)
- print 'Original statements: %d' % o
- print 'After global optimization: %d' % g
- print 'After basic blocks optimization: %d' % b
- print 'Speedup: %d (%d%%)' \
- % (b - o, int((b - o) / o * 100))
- return opt_blocks
|