comparison 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
comparison
equal deleted inserted replaced
170:4348da5ca307 171:3eb9b9e2958d
1 # IR-Structures: 1 # IR-Structures:
2 from .instruction import *
3 from .basicblock import BasicBlock
2 4
3 class Module: 5 class Module:
4 """ Main container for a piece of code. """ 6 """ Main container for a piece of code. """
5 def __init__(self, name): 7 def __init__(self, name):
6 self.name = name 8 self.name = name
7 self.instructions = [] 9 self.bbs = []
8 def __repr__(self): 10 def __repr__(self):
9 return 'IR-module [{0}]'.format(self.name) 11 return 'IR-module [{0}]'.format(self.name)
10 def getInstructions(self): 12 def getInstructions(self):
11 return self.instructions 13 ins = []
14 for bb in self.bbs:
15 ins += bb.Instructions
16 return ins
12 Instructions = property(getInstructions) 17 Instructions = property(getInstructions)
18 def addBB(self, bb):
19 self.bbs.append(bb)
20 def getBBs(self):
21 return self.bbs
22 BasicBlocks = property(getBBs)
13 def dump(self): 23 def dump(self):
14 print(self) 24 print(self)
15 for i in self.Instructions: 25 for i in self.Instructions:
16 print(i) 26 print(i, 'live vars:', list(i.live_in), 'uses', list(i.uses), 'defs', list(i.defs))
17 print('END') 27 print('END')
28 def dumpgv(self, outf):
29 outf.write('digraph G \n{\n')
30 for i in self.Instructions:
31 outf.write('{0} [label="{1}"];\n'.format(id(i), i))
32 for succ in i.succ:
33 outf.write('"{0}" -> "{1}" [label="{2}"];\n'.format(id(i), id(succ), succ.live_in))
34 outf.write('}\n')
18 35
36 # Analysis functions:
37 def check(self):
38 """ Perform sanity check on module """
39 for i in self.Instructions:
40 for t in i.defs:
41 assert type(t) is Value, "def must be Value, not {0}".format(type(t))
42 for t in i.uses:
43 assert type(t) is Value, "use must be Value, not {0}".format(type(t))
44 def analyze(self):
45 # Determine pred and succ:
46 def link(a, b):
47 a.succ.add(b)
48 b.pred.add(a)
49 for bb in self.bbs:
50 if not bb.Empty:
51 if len(bb.Instructions) > 1:
52 for i1, i2 in zip(bb.Instructions[:-1], bb.Instructions[1:]):
53 link(i1, i2)
54 else:
55 print('Only 1 long!', bb, bb.Instructions)
56 if type(bb.LastIns) is ConditionalBranch:
57 link(bb.LastIns, bb.LastIns.lab1.FirstIns)
58 link(bb.LastIns, bb.LastIns.lab2.FirstIns)
59 if type(bb.LastIns) is Branch:
60 link(bb.LastIns, bb.LastIns.target.FirstIns)
61 else:
62 print('Empty!', bb)
63 # We now have cfg
64
65 # Determine liveness:
66 for i in self.Instructions:
67 i.live_in = set()
68 i.live_out = set()
69 for z in range(50):
70 # TODO iterate until converge
71 for i in self.Instructions:
72 lo_mk = i.live_out.difference(i.defs)
73 i.live_in = i.uses.union(lo_mk)
74 lo = set()
75 for s in i.succ:
76 lo = lo.union(s.live_in)
77 i.live_out = lo
78 def constantProp(self):
79 """ Constant propagation. Pre-calculate constant values """
80 for i in self.Instructions:
81 if type(i) is ImmLoad:
82 i.target.constval = i.value
83 elif type(i) is BinaryOperator:
84 a = i.value1
85 b = i.value2
86 if i.value1.constval and i.value2.constval:
87 op = i.operation
88 if op == '+':
89 i.result.constval = a + b
90 else:
91 raise NotImplementedError(op)
92 else:
93 i.result.constval = None
94
95 def registerAllocate(self, regs):
96 print(regs)
97 allVals = []
98 # construct interference:
99 for i in self.Instructions:
100 for v in i.live_in:
101 allVals.append(v)
102 for v2 in i.live_in:
103 if v != v2:
104 v.interferes.add(v2)
105 # assign random registers:
106 print(allVals)
107 regs = set(regs)
108 for v in allVals:
109 takenregs = set([iv.reg for iv in v.interferes])
110 r2 = list(regs.difference(takenregs))
111 # Pick next available:
112 v.reg = r2[0]
113