optimize.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. from utils import Statement as S, find_basic_blocks
  2. def optimize_branch_jump_label(statements):
  3. """Optimize jumps after branches."""
  4. out_statements = []
  5. for i in xrange(len(statements)):
  6. if i + 3 > len(statements):
  7. out_statements.append(statements[i])
  8. continue
  9. stype, name, args = statements[i]
  10. stype2, name2, args2 = statements[i + 1]
  11. stype3, name3, args3 = statements[i + 2]
  12. if stype == 'command' and name == 'beq' and \
  13. stype2 == 'command' and name2 in ['j', 'jal'] and \
  14. stype3 == 'label' and name3 == args['args'][2]:
  15. out_statements.append(('command', 'bne', \
  16. {'args': [args['args'][0], args['args'][1], args2['args'][0]]}))
  17. out_statements.append(statements[1 + 2])
  18. i += 3
  19. else:
  20. out_statements.append(statements[i])
  21. return out_statements
  22. def optimize_global(statements):
  23. """Optimize one-line statements in entire code."""
  24. old_len = -1
  25. while old_len != len(statements):
  26. old_len = len(statements)
  27. while not statements.end():
  28. s = statements.read()
  29. # mov $regA,$regB -> --- remove it
  30. if s.is_command() and s.name == 'move' and s[0] == s[1]:
  31. statements.replace(1, [])
  32. # mov $regA,$regB -> instr $regA, $regB, ...
  33. # instr $regA, $regA, ...
  34. if s.is_command() and s.name == 'move':
  35. ins = statements.peek()
  36. if ins and len(ins) >= 2 and ins[0] == s[0] and ins[1] == s[0]:
  37. ins[1] = s[1]
  38. # instr $regA, ... -> instr $4, ...
  39. # mov $4, $regA jal XX
  40. # jal XX
  41. if s.is_command() and len(s):
  42. following = statements.peek(2)
  43. if len(following) == 2:
  44. mov, jal = following
  45. if mov.name == 'move' and mov[1] == s[0] \
  46. and jal.name == 'jal':
  47. s[0] = mov[0]
  48. statements.replace(1, [], start=statements.pointer + 1)
  49. # sw $regA, XX -> sw $regA, XX
  50. # ld $regA, XX
  51. # shift $regA, $regA, 0 -> --- remove it
  52. if s.is_shift() and s[0] == s[1] and s[2] == 0:
  53. statements.replace(1, [])
  54. # add $regA, $regA, X -> lw ..., X($regA)
  55. # lw ..., 0($regA)
  56. # beq ..., $Lx -> bne ..., $Ly
  57. # j $Ly $Lx:
  58. # $Lx:
  59. #if block.peek(3):
  60. # block.replace(3, [nieuwe statements])
  61. return statements
  62. def optimize_blocks(blocks):
  63. """Call the optimizer for each basic block. Do this several times until
  64. no more optimizations are achieved."""
  65. changed = True
  66. while changed:
  67. changed = False
  68. optimized = []
  69. for block in blocks:
  70. block_changed, b = optimize_block(block)
  71. optimized.append(b)
  72. if block_changed:
  73. changed = True
  74. blocks = optimized
  75. return reduce(lambda a, b: a + b, blocks, [])
  76. def optimize_block(statements):
  77. """Optimize a basic block."""
  78. changed = False
  79. output_statements = []
  80. for statement in statements:
  81. new_statement = statement
  82. output_statements.append(new_statement)
  83. return changed, output_statements
  84. def optimize(original, verbose=0):
  85. """optimization wrapper function, calls global and basic-block level
  86. optimization functions."""
  87. # Optimize on a global level
  88. opt_global = optimize_global(original)
  89. # Optimize basic blocks
  90. basic_blocks = find_basic_blocks(opt_global)
  91. blocks = optimize_blocks(basic_blocks)
  92. opt_blocks = reduce(lambda a, b: a.statements + b.statements, blocks)
  93. if verbose:
  94. o = len(original)
  95. g = len(opt_global)
  96. b = len(opt_blocks)
  97. print 'Original statements: %d' % o
  98. print 'After global optimization: %d' % g
  99. print 'After basic blocks optimization: %d' % b
  100. print 'Speedup: %d (%d%%)' \
  101. % (b - o, int((b - o) / o * 100))
  102. return opt_blocks