diff python/ir/module.py @ 171:3eb9b9e2958d

Improved IR code
author Windel Bouwman
date Wed, 03 Apr 2013 22:20:20 +0200
parents 4348da5ca307
children 5a7d37d615ee
line wrap: on
line diff
--- a/python/ir/module.py	Fri Mar 29 17:33:17 2013 +0100
+++ b/python/ir/module.py	Wed Apr 03 22:20:20 2013 +0200
@@ -1,18 +1,113 @@
 # IR-Structures:
+from .instruction import *
+from .basicblock import BasicBlock
 
 class Module:
    """ Main container for a piece of code. """
    def __init__(self, name):
       self.name = name
-      self.instructions = []
+      self.bbs = []
    def __repr__(self):
       return 'IR-module [{0}]'.format(self.name)
    def getInstructions(self):
-      return self.instructions
+      ins = []
+      for bb in self.bbs:
+         ins += bb.Instructions
+      return ins
    Instructions = property(getInstructions)
+   def addBB(self, bb):
+      self.bbs.append(bb)
+   def getBBs(self):
+      return self.bbs
+   BasicBlocks = property(getBBs)
    def dump(self):
       print(self)
       for i in self.Instructions:
-         print(i)
+         print(i, 'live vars:', list(i.live_in), 'uses', list(i.uses), 'defs', list(i.defs))
       print('END')
+   def dumpgv(self, outf):
+      outf.write('digraph G \n{\n')
+      for i in self.Instructions:
+         outf.write('{0} [label="{1}"];\n'.format(id(i), i))
+         for succ in i.succ:
+            outf.write('"{0}" -> "{1}" [label="{2}"];\n'.format(id(i), id(succ), succ.live_in))
+      outf.write('}\n')
 
+   # Analysis functions:
+   def check(self):
+      """ Perform sanity check on module """
+      for i in self.Instructions:
+         for t in i.defs:
+            assert type(t) is Value, "def must be Value, not {0}".format(type(t))
+         for t in i.uses:
+            assert type(t) is Value, "use must be Value, not {0}".format(type(t))
+   def analyze(self):
+      # Determine pred and succ:
+      def link(a, b):
+         a.succ.add(b)
+         b.pred.add(a)
+      for bb in self.bbs:
+         if not bb.Empty:
+            if len(bb.Instructions) > 1:
+               for i1, i2 in zip(bb.Instructions[:-1], bb.Instructions[1:]):
+                  link(i1, i2)
+            else:
+               print('Only 1 long!', bb, bb.Instructions)
+            if type(bb.LastIns) is ConditionalBranch:
+               link(bb.LastIns, bb.LastIns.lab1.FirstIns)
+               link(bb.LastIns, bb.LastIns.lab2.FirstIns)
+            if type(bb.LastIns) is Branch:
+               link(bb.LastIns, bb.LastIns.target.FirstIns)
+         else:
+            print('Empty!', bb)
+      # We now have cfg
+
+      # Determine liveness:
+      for i in self.Instructions:
+         i.live_in = set()
+         i.live_out = set()
+      for z in range(50):
+         # TODO iterate until converge
+         for i in self.Instructions:
+            lo_mk = i.live_out.difference(i.defs)
+            i.live_in = i.uses.union(lo_mk)
+            lo = set()
+            for s in i.succ:
+               lo = lo.union(s.live_in)
+            i.live_out = lo
+   def constantProp(self):
+      """ Constant propagation. Pre-calculate constant values """
+      for i in self.Instructions:
+         if type(i) is ImmLoad:
+            i.target.constval = i.value
+         elif type(i) is BinaryOperator:
+            a = i.value1
+            b = i.value2
+            if i.value1.constval and i.value2.constval:
+               op = i.operation
+               if op == '+':
+                  i.result.constval = a + b
+               else:
+                  raise NotImplementedError(op)
+            else:
+               i.result.constval = None
+
+   def registerAllocate(self, regs):
+      print(regs)
+      allVals = []
+      # construct interference:
+      for i in self.Instructions:
+         for v in i.live_in:
+            allVals.append(v)
+            for v2 in i.live_in:
+               if v != v2:
+                  v.interferes.add(v2)
+      # assign random registers:
+      print(allVals)
+      regs = set(regs)
+      for v in allVals:
+         takenregs = set([iv.reg for iv in v.interferes])
+         r2 = list(regs.difference(takenregs))
+         # Pick next available:
+         v.reg = r2[0]
+