Add a very basic optimization pass
authorDavid Kerkeslager <kerkeslager@gmail.com>
Wed, 24 Jul 2019 18:00:40 +0000 (14:00 -0400)
committerDavid Kerkeslager <kerkeslager@gmail.com>
Wed, 24 Jul 2019 18:00:40 +0000 (14:00 -0400)
main.py
optimization.py [new file with mode: 0644]

diff --git a/main.py b/main.py
index 3045554..198072e 100644 (file)
--- a/main.py
+++ b/main.py
@@ -5,6 +5,7 @@ import crossplatform_ir_generation
 import desugaring
 import generation
 import normalization
 import desugaring
 import generation
 import normalization
+import optimization
 import parsing
 import tokenization
 import transformation
 import parsing
 import tokenization
 import transformation
@@ -32,5 +33,6 @@ with open(destination_path, 'w') as f:
 
 # This is the crossplatform IR generation path
 crossplatform_ir = crossplatform_ir_generation.generate(converted)
 
 # This is the crossplatform IR generation path
 crossplatform_ir = crossplatform_ir_generation.generate(converted)
-outputted = crossplatform_ir_generation.output(crossplatform_ir)
+optimized = optimization.optimize(crossplatform_ir)
+outputted = crossplatform_ir_generation.output(optimized)
 print(outputted)
 print(outputted)
diff --git a/optimization.py b/optimization.py
new file mode 100644 (file)
index 0000000..7beef77
--- /dev/null
@@ -0,0 +1,49 @@
+from crossplatform_ir_generation import CIRProgram, CIRInstruction, CIRLabel
+
+PUSHING_INSTRUCTIONS_WITHOUT_SIDE_EFFECTS = set(
+    ('push',),
+)
+
+def push_drop_optimization(ir):
+    ir = tuple(ir)
+
+    i = 0
+
+    while i < len(ir):
+        if isinstance(ir[i], CIRInstruction)\
+                and ir[i].instruction in PUSHING_INSTRUCTIONS_WITHOUT_SIDE_EFFECTS\
+                and i + 1 < len(ir)\
+                and isinstance(ir[i + 1], CIRInstruction)\
+                and ir[i + 1].instruction == 'drop':
+            i += 2
+        else:
+            yield ir[i]
+            i += 1
+
+# TODO This can be smarter
+def unused_pop_optimization(ir):
+    ir = tuple(ir)
+
+    used_symbols = set()
+
+    for entry in ir:
+        # TODO Having symbols be a string starting with "sym" is a bit hacky
+        if isinstance(entry, CIRInstruction)\
+                and entry.instruction != 'pop'\
+                and isinstance(entry.argument, str)\
+                and entry.argument.startswith('sym'):
+            used_symbols.add(entry.argument)
+
+    for entry in ir:
+        if isinstance(entry, CIRInstruction) and entry.instruction == 'pop' and entry.argument not in used_symbols:
+            yield CIRInstruction(instruction='drop', argument=None)
+        else:
+            yield entry
+
+def optimize(cir_program):
+    ir = cir_program.entry_list
+
+    ir = push_drop_optimization(ir)
+    ir = unused_pop_optimization(ir)
+
+    return CIRProgram(entry_list=tuple(ir))