comparison python/ppci/transform.py @ 300:158068af716c

yafm
author Windel Bouwman
date Tue, 03 Dec 2013 18:00:22 +0100
parents python/transform.py@9417caea2eb3
children 6753763d3bec
comparison
equal deleted inserted replaced
299:674789d9ff37 300:158068af716c
1 """
2 Transformation to optimize IR-code
3 """
4
5 import logging
6 import ir
7 # Standard passes:
8
9 class FunctionPass:
10 def __init__(self):
11 self.logger = logging.getLogger('optimize')
12
13 def run(self, ir):
14 """ Main entry point for the pass """
15 self.logger.info('Running pass {}'.format(type(self)))
16 ir.check()
17 self.prepare()
18 for f in ir.Functions:
19 self.onFunction(f)
20 ir.check()
21
22 def onFunction(self, f):
23 """ Override this virtual method """
24 raise NotImplementedError()
25
26 def prepare(self):
27 pass
28
29
30 class BasicBlockPass(FunctionPass):
31 def onFunction(self, f):
32 for bb in f.Blocks:
33 self.onBasicBlock(bb)
34
35 def onBasicBlock(self, bb):
36 """ Override this virtual method """
37 raise NotImplementedError()
38
39
40 class InstructionPass(BasicBlockPass):
41 def onBasicBlock(self, bb):
42 for ins in iter(bb.Instructions):
43 self.onInstruction(ins)
44
45 def onInstruction(self, ins):
46 """ Override this virtual method """
47 raise NotImplementedError()
48
49
50 class BasePass(BasicBlockPass):
51 def onBasicBlock(self, bb):
52 pass
53
54
55 # Usefull transforms:
56 class ConstantFolder(BasePass):
57 def __init__(self):
58 super().__init__()
59 self.ops = {}
60 self.ops['+'] = lambda x, y: x + y
61 self.ops['-'] = lambda x, y: x - y
62 self.ops['*'] = lambda x, y: x * y
63 self.ops['<<'] = lambda x, y: x << y
64
65 def postExpr(self, expr):
66 if type(i) is BinaryOperator and i.operation in self.ops.keys() and type(i.a) is Const and type(i.b) is Const:
67 vr = self.ops[i.operation](i.a.value, i.b.value)
68 return Const(vr)
69 else:
70 return expr
71
72
73 class DeadCodeDeleter(BasicBlockPass):
74 def onBasicBlock(self, bb):
75 def instructionUsed(ins):
76 if not type(ins) in [ImmLoad, BinaryOperator]:
77 return True
78 if len(ins.defs) == 0:
79 # In case this instruction does not define any
80 # variables, assume it is usefull.
81 return True
82 return any(d.Used for d in ins.defs)
83
84 change = True
85 while change:
86 change = False
87 for i in bb.Instructions:
88 if instructionUsed(i):
89 continue
90 bb.removeInstruction(i)
91 change = True
92
93
94 class CommonSubexpressionElimination(BasicBlockPass):
95 def onBasicBlock(self, bb):
96 constMap = {}
97 to_remove = []
98 for i in bb.Instructions:
99 if isinstance(i, ImmLoad):
100 if i.value in constMap:
101 t_new = constMap[i.value]
102 t_old = i.target
103 logging.debug('Replacing {} with {}'.format(t_old, t_new))
104 t_old.replaceby(t_new)
105 to_remove.append(i)
106 else:
107 constMap[i.value] = i.target
108 elif isinstance(i, BinaryOperator):
109 k = (i.value1, i.operation, i.value2)
110 if k in constMap:
111 t_old = i.result
112 t_new = constMap[k]
113 logging.debug('Replacing {} with {}'.format(t_old, t_new))
114 t_old.replaceby(t_new)
115 to_remove.append(i)
116 else:
117 constMap[k] = i.result
118 for i in to_remove:
119 logging.debug('removing {}'.format(i))
120 bb.removeInstruction(i)
121
122
123 class CleanPass(FunctionPass):
124 def onFunction(self, f):
125 removeEmptyBasicBlocks(f)
126
127
128 def removeEmptyBlocks(f):
129 """ Remove empty basic blocks from function. """
130 # If a block only contains a branch, it can be removed:
131 empty = lambda b: type(b.FirstInstruction) is ir.Jump
132 empty_blocks = list(filter(empty, f.Blocks))
133 for b in empty_blocks:
134 # Update predecessors
135 preds = b.Predecessors
136 if b not in preds + [f.entry]:
137 # Do not remove if preceeded by itself
138 tgt = b.LastInstruction.target
139 for pred in preds:
140 pred.LastInstruction.changeTarget(b, tgt)
141 logging.debug('Removing empty block: {}'.format(b))
142 f.removeBlock(b)