program.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. from statement import Statement as S, Block
  2. from dataflow import find_basic_blocks, generate_flow_graph
  3. from optimize.redundancies import remove_redundant_jumps, remove_redundancies
  4. from optimize.advanced import eliminate_common_subexpressions, \
  5. fold_constants, copy_propagation, eliminate_dead_code
  6. from writer import write_statements
  7. import liveness
  8. import reaching_definitions
  9. class Program(Block):
  10. def __len__(self):
  11. """Get the number of statements in the program."""
  12. return len(self.statements) if hasattr(self, 'statements') \
  13. else reduce(lambda a, b: len(a) + len(b), self.blocks, 0)
  14. def get_statements(self, add_block_comments=False):
  15. """Concatenate the statements of all blocks and return the resulting
  16. list."""
  17. if hasattr(self, 'statements'):
  18. return self.statements
  19. # Only add block start and end comments when in debug mode
  20. if add_block_comments and self.debug:
  21. get_id = lambda b: b.bid
  22. statements = []
  23. for b in self.blocks:
  24. message = ' Block %d (%d statements), edges from: %s' \
  25. % (b.bid, len(b), map(get_id, b.edges_from))
  26. if hasattr(b, 'live_in'):
  27. message += ', LIVE_in: %s' % list(b.live_in)
  28. if hasattr(b, 'reach_in'):
  29. message += ', REACH_in: %s' % list(b.reach_in)
  30. statements.append(S('comment', message, block=False))
  31. statements += b.statements
  32. message = ' End of block %d, edges to: %s' \
  33. % (b.bid, map(get_id, b.edges_to))
  34. if hasattr(b, 'live_out'):
  35. message += ', LIVE_out: %s' % list(b.live_out)
  36. if hasattr(b, 'reach_out'):
  37. message += ', REACH_out: %s' % list(b.reach_out)
  38. statements.append(S('comment', message, block=False))
  39. return statements
  40. return reduce(lambda a, b: a + b,
  41. [b.statements for b in self.blocks])
  42. def count_instructions(self):
  43. """Count the number of statements that are commands or labels."""
  44. return len(filter(lambda s: s.is_command() or s.is_label(),
  45. self.get_statements()))
  46. def optimize_global(self):
  47. """Optimize on a global level."""
  48. remove_redundant_jumps(self)
  49. def optimize_blocks(self):
  50. """Optimize on block level. Keep executing all optimizations until no
  51. more changes occur."""
  52. self.program_iterations = self.block_iterations = 0
  53. program_changed = True
  54. while program_changed:
  55. self.program_iterations += 1
  56. program_changed = False
  57. for block in self.blocks:
  58. self.block_iterations += 1
  59. block_changed = True
  60. while block_changed:
  61. block_changed = False
  62. if remove_redundancies(block):
  63. block_changed = True
  64. if eliminate_common_subexpressions(block):
  65. block_changed = True
  66. if fold_constants(block):
  67. block_changed = True
  68. if copy_propagation(block):
  69. block_changed = True
  70. if eliminate_dead_code(block):
  71. block_changed = True
  72. if block_changed:
  73. program_changed = True
  74. def find_basic_blocks(self):
  75. """Divide the statement list into basic blocks."""
  76. self.blocks = find_basic_blocks(self.statements)
  77. for b in self.blocks:
  78. b.debug = self.debug
  79. # Remove the old statement list, since it will probably change
  80. del self.statements
  81. def perform_dataflow_analysis(self):
  82. """Perform dataflow analysis:
  83. - Divide the statement list into basic blocks
  84. - Generate flow graph
  85. - Create liveness sets: def, use, in, out
  86. - Create reaching definitions sets: gen, kill, in, out"""
  87. self.find_basic_blocks()
  88. generate_flow_graph(self.blocks)
  89. liveness.create_in_out(self.blocks)
  90. reaching_definitions.create_in_out(self.blocks)
  91. def save(self, filename):
  92. """Save the program in the specified file."""
  93. f = open(filename, 'w+')
  94. f.write(write_statements(self.get_statements(True)))
  95. f.close()