optimize.py 4.2 KB

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