Add a very basic optimization pass
[fur] / optimization.py
1 from crossplatform_ir_generation import CIRProgram, CIRInstruction, CIRLabel
2
3 PUSHING_INSTRUCTIONS_WITHOUT_SIDE_EFFECTS = set(
4     ('push',),
5 )
6
7 def push_drop_optimization(ir):
8     ir = tuple(ir)
9
10     i = 0
11
12     while i < len(ir):
13         if isinstance(ir[i], CIRInstruction)\
14                 and ir[i].instruction in PUSHING_INSTRUCTIONS_WITHOUT_SIDE_EFFECTS\
15                 and i + 1 < len(ir)\
16                 and isinstance(ir[i + 1], CIRInstruction)\
17                 and ir[i + 1].instruction == 'drop':
18             i += 2
19         else:
20             yield ir[i]
21             i += 1
22
23 # TODO This can be smarter
24 def unused_pop_optimization(ir):
25     ir = tuple(ir)
26
27     used_symbols = set()
28
29     for entry in ir:
30         # TODO Having symbols be a string starting with "sym" is a bit hacky
31         if isinstance(entry, CIRInstruction)\
32                 and entry.instruction != 'pop'\
33                 and isinstance(entry.argument, str)\
34                 and entry.argument.startswith('sym'):
35             used_symbols.add(entry.argument)
36
37     for entry in ir:
38         if isinstance(entry, CIRInstruction) and entry.instruction == 'pop' and entry.argument not in used_symbols:
39             yield CIRInstruction(instruction='drop', argument=None)
40         else:
41             yield entry
42
43 def optimize(cir_program):
44     ir = cir_program.entry_list
45
46     ir = push_drop_optimization(ir)
47     ir = unused_pop_optimization(ir)
48
49     return CIRProgram(entry_list=tuple(ir))