diff python/ppci/mem2reg.py @ 300:158068af716c

yafm
author Windel Bouwman
date Tue, 03 Dec 2013 18:00:22 +0100
parents python/mem2reg.py@9417caea2eb3
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/ppci/mem2reg.py	Tue Dec 03 18:00:22 2013 +0100
@@ -0,0 +1,70 @@
+import logging
+from transform import FunctionPass
+from ir import *
+
+def isAllocPromotable(allocinst):
+    # Check if alloc value is only used by load and store operations.
+    assert type(allocinst) is Alloc
+    return all(type(use) in [Load, Store] for use in allocinst.value.used_by)
+
+
+class Mem2RegPromotor(FunctionPass):
+    def promoteSingleBlock(self, ai):
+        v = ai.value
+        bb = ai.Block
+
+        # Replace all loads with the value:
+        loads = [i for i in v.used_by if isinstance(i, Load)]
+        stores = [i for i in v.used_by if isinstance(i, Store)]
+        stores.sort(key=lambda s: s.Position)
+        stores.reverse()
+
+        for load in loads:
+            idx = load.Position
+            # Search upwards:
+            for store in stores:
+                if store.Position < load.Position:
+                    break
+            load.value.replaceby(store.value)
+            logging.debug('replaced {} with {}'.format(load, store.value))
+            bb.removeInstruction(load)
+
+        # Remove store instructions:
+        for store in stores:
+            sv = store.value
+            logging.debug('removing {}'.format(store))
+            bb.removeInstruction(store)
+            #assert sv.Used
+        
+        # Remove alloca instruction:
+        assert not ai.value.Used, ai.value.used_by
+        bb.removeInstruction(ai)
+
+    def promote(self, ai):
+        # Find load operations and replace them with assignments
+        v = ai.value
+        if len(ai.value.UsedInBlocks) == 1:
+            self.promoteSingleBlock(ai)
+            return
+        
+        loads = [i for i in v.used_by if isinstance(i, Load)]
+        stores = [i for i in v.used_by if isinstance(i, Store)]
+
+        # Each store instruction can be removed (later).
+        # Instead of storing the value, we use it 
+        # where the load would have been!
+        replMap = {}
+        for store in stores:
+            replMap[store] = store.value
+
+        # for each load, track back what the defining store
+        # was.
+        for load in loads:
+            pass
+
+    def onFunction(self, f):
+        for bb in f.BasicBlocks:
+            allocs = [i for i in bb.Instructions if isinstance(i, Alloc)]
+            for i in allocs:
+                if isAllocPromotable(i):
+                    self.promote(i)