diff python/transform.py @ 253:74c6a20302d5

Added better logging
author Windel Bouwman
date Wed, 31 Jul 2013 17:57:03 +0200
parents c4370696ccc7
children 7416c923a02a
line wrap: on
line diff
--- a/python/transform.py	Tue Jul 30 17:57:46 2013 +0200
+++ b/python/transform.py	Wed Jul 31 17:57:03 2013 +0200
@@ -2,20 +2,24 @@
  Transformation to optimize IR-code
 """
 
+import logging
 from ir import *
 # Standard passes:
 
 class FunctionPass:
-   def run(self, ir):
-      """ Main entry point for the pass """
-      self.prepare()
-      for f in ir.Functions:
-         self.onFunction(f)
-   def onFunction(self, f):
-      """ Override this virtual method """
-      raise NotImplementedError()
-   def prepare(self):
-      pass
+    def run(self, ir):
+        """ Main entry point for the pass """
+        logging.info('Running pass {}'.format(type(self)))
+        self.prepare()
+        for f in ir.Functions:
+            self.onFunction(f)
+
+    def onFunction(self, f):
+        """ Override this virtual method """
+        raise NotImplementedError()
+
+    def prepare(self):
+        pass
 
 
 class BasicBlockPass(FunctionPass):
@@ -64,13 +68,15 @@
             self.constMap[i.result] = vr
             i.removeDef(i.result)
             i2 = ImmLoad(i.result, vr)
-            print('Replacing', i)
+            logging.debug('Replacing {}'.format(i))
             i.Parent.replaceInstruction(i, i2)
 
 
 class DeadCodeDeleter(BasicBlockPass):
     def onBasicBlock(self, bb):
         def instructionUsed(ins):
+            if not type(ins) in [ImmLoad, BinaryOperator]:
+                return True
             if len(ins.defs) == 0:
                 # In case this instruction does not define any 
                 # variables, assume it is usefull.
@@ -96,6 +102,7 @@
                 if i.value in constMap:
                     t_new = constMap[i.value]
                     t_old = i.target
+                    logging.debug('Replacing {} with {}'.format(t_old, t_new))
                     for ui in t_old.used_by:
                         ui.replaceValue(t_old, t_new)
                     to_remove.append(i)
@@ -104,137 +111,37 @@
             elif isinstance(i, BinaryOperator):
                 k = (i.value1, i.operation, i.value2)
                 if k in constMap:
-                    print('Duplicate binop!', i)
                     t_old = i.result
                     t_new = constMap[k]
+                    logging.debug('Replacing {} with {}'.format(t_old, t_new))
                     for ui in t_old.used_by:
                         ui.replaceValue(t_old, t_new)
                     to_remove.append(i)
                 else:
                     constMap[k] = i.result
         for i in to_remove:
-            print('removing ', i)
+            logging.debug('removing {}'.format(i))
             bb.removeInstruction(i)
 
-            
-
 
 class CleanPass(FunctionPass):
     def onFunction(self, f):
         bbs = list(f.BasicBlocks)
         for bb in bbs:
-         # TODO: determine check for 'empty'
-
-         # If a block only contains a branch, it can be removed:
-         if len(bb.Instructions) == 1 and type(bb.LastInstruction) is Branch:
-            # This block is empty.
-            # find predecessors of this block and replace this block reference with the jumped reference.
-            ins = bb.LastInstruction
-            preds = bb.Predecessors
-            if bb in preds:
+            # If a block only contains a branch, it can be removed:
+            if len(bb.Instructions) == 1 and type(bb.LastInstruction) is Branch:
+                # This block is empty.
+                # find predecessors of this block and replace this block reference with the jumped reference.
+                ins = bb.LastInstruction
+                preds = bb.Predecessors
+                if bb in preds:
                     # Do not remove if preceeded by itself
                     pass
-            else:
+                else:
                     for pred in bb.Predecessors:
                           pred.LastInstruction.changeTarget(bb, ins.target)
                     f.removeBasicBlock(bb)
 
 
-def isAllocPromotable(allocinst):
-   # Check if alloc value is only used by load and store operations.
-   assert type(allocinst) is Alloc
-   for use in allocinst.value.used_by:
-      if not type(use) in [Load, Store]:
-         # TODO: check volatile
-         return False
-         otherUse = True
-   return True
 
 
-class Mem2RegPromotor(FunctionPass):
-    def promoteSingleBlock(self, ai):
-        print('Single block:', 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()
-        print(stores)
-
-        for load in loads:
-            idx = load.Position
-            # Search upwards:
-            for store in stores:
-                if store.Position < load.Position:
-                    break
-            #print('replace {} with {}'.format(load, store.value))
-            for use_ins in load.value.used_by:
-                use_ins.replaceValue(load.value, store.value)
-            assert not load.value.Used
-            print('removing {}'.format(load))
-            bb.removeInstruction(load)
-
-        # Remove store instructions:
-        for store in stores:
-            sv = store.value
-            print('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:
-            print(load)
-
-    def onFunction(self, f):
-        # TODO
-        for bb in f.BasicBlocks:
-            allocs = [i for i in bb.Instructions if isinstance(i, Alloc)]
-            for i in allocs:
-                print(i, isAllocPromotable(i))
-                if isAllocPromotable(i):
-                    self.promote(i)
-
-def optimize(ir):
-    cf = ConstantFolder()
-    dcd = DeadCodeDeleter()
-    m2r = Mem2RegPromotor()
-    clr = CleanPass()
-    cse = CommonSubexpressionElimination()
-    ir.check()
-    cf.run(ir)
-    dcd.run(ir)
-    ir.check()
-    clr.run(ir)
-    ir.check()
-    m2r.run(ir)
-    ir.check()
-    cse.run(ir)
-    ir.check()
-