diff python/registerallocator.py @ 269:5f8c04a8d26b

Towards better modularity
author Windel Bouwman
date Sun, 18 Aug 2013 17:43:18 +0200
parents a51b3c956386
children cdc76d183bcc
line wrap: on
line diff
--- a/python/registerallocator.py	Wed Aug 14 20:12:40 2013 +0200
+++ b/python/registerallocator.py	Sun Aug 18 17:43:18 2013 +0200
@@ -1,33 +1,73 @@
+
+import graph
+
+class InterferenceGraphNode(graph.Node):
+    def __init__(self, g, varname):
+        super().__init__(g)
+        self.varname = varname
+
+    def __repr__(self):
+        return '{}'.format(self.varname)
+
+
+class InterferenceGraph(graph.Graph):
+    def __init__(self, flowgraph):
+        """ Create a new interference graph from a flowgraph """
+        super().__init__()
+        # Mapping from node to live set
+        self.liveMap = {}
+        self.tempMap = {}
+        # Calculate liveness in CFG:
+        ###
+        # Liveness:
+        #  in[n] = use[n] UNION (out[n] - def[n])
+        #  out[n] = for s in n.succ in union in[s]
+        ###
+        for n in flowgraph.nodes:
+            n.live_in = set()
+            n.live_out = set()
+        # Dataflow fixed point iteration:
+        change = True
+        while change:
+            change = False
+            for n in flowgraph.nodes:
+                _in = n.live_in
+                _out = n.live_out
+                n.live_in = n.uses | (n.live_out - n.defs)
+                if n.succ:
+                    n.live_out = set.union(*(s.live_in for s in n.succ))
+                else:
+                    n.live_out = set()
+                change = change or (_in != n.live_in) or (_out != n.live_out)
+        # Construct interference graph:
+        for n in flowgraph.nodes:
+            for tmp in n.live_out:
+                n1 = self.getNode(tmp)
+                for tmp2 in (n.live_out - {tmp}):
+                    n2 = self.getNode(tmp2)
+                    self.addEdge(n1, n2)
+
+    def getNode(self, tmp):
+        if tmp not in self.tempMap:
+            self.tempMap[tmp] = self.newNode(tmp)
+        return self.tempMap[tmp]
+
+    def newNode(self, varname):
+        n = InterferenceGraphNode(self, varname)
+        self.nodes.append(n)
+        return n
+
 
 class RegisterAllocator:
-   def live_analyze(self):
-      # 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 registerAllocate(self, ir, regs):
-      allVals = []
-      # construct interference:
-      for i in ir.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:
-      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]
+    """ Target independent register allocator """
+    def registerAllocate(self, ig, regs):
+        """ Color the given interference graph with the provided registers """
+        self.regMap = {}
+        # TODO: implement ;)
+        regs = set(regs)
+        for n in ig.nodes:
+            print(n)
 
+        # TODO: implement spilling
+        # TODO: implement coalescing
+