annotate python/ppci/transform.py @ 334:6f4753202b9a

Added more recipes
author Windel Bouwman
date Thu, 13 Feb 2014 22:02:08 +0100
parents e30a77ae359b
children d1ecc493384e
rev   line source
240
6259856841a0 Remove project
Windel Bouwman
parents: 239
diff changeset
1 """
6259856841a0 Remove project
Windel Bouwman
parents: 239
diff changeset
2 Transformation to optimize IR-code
6259856841a0 Remove project
Windel Bouwman
parents: 239
diff changeset
3 """
6259856841a0 Remove project
Windel Bouwman
parents: 239
diff changeset
4
253
74c6a20302d5 Added better logging
Windel Bouwman
parents: 252
diff changeset
5 import logging
301
6753763d3bec merge codegen into ppci package
Windel Bouwman
parents: 300
diff changeset
6 from . import ir
173
c1d2b6b9f9a7 Rework into passes
Windel Bouwman
parents:
diff changeset
7 # Standard passes:
c1d2b6b9f9a7 Rework into passes
Windel Bouwman
parents:
diff changeset
8
c1d2b6b9f9a7 Rework into passes
Windel Bouwman
parents:
diff changeset
9 class FunctionPass:
255
7416c923a02a Added more logging
Windel Bouwman
parents: 253
diff changeset
10 def __init__(self):
316
56e6ff84f646 Fixed burn led demo
Windel Bouwman
parents: 301
diff changeset
11 self.logger = logging.getLogger(str(self.__class__.__name__))
255
7416c923a02a Added more logging
Windel Bouwman
parents: 253
diff changeset
12
253
74c6a20302d5 Added better logging
Windel Bouwman
parents: 252
diff changeset
13 def run(self, ir):
74c6a20302d5 Added better logging
Windel Bouwman
parents: 252
diff changeset
14 """ Main entry point for the pass """
334
6f4753202b9a Added more recipes
Windel Bouwman
parents: 317
diff changeset
15 self.logger.debug('Running pass {}'.format(self.__class__.__name__))
253
74c6a20302d5 Added better logging
Windel Bouwman
parents: 252
diff changeset
16 self.prepare()
74c6a20302d5 Added better logging
Windel Bouwman
parents: 252
diff changeset
17 for f in ir.Functions:
74c6a20302d5 Added better logging
Windel Bouwman
parents: 252
diff changeset
18 self.onFunction(f)
74c6a20302d5 Added better logging
Windel Bouwman
parents: 252
diff changeset
19
74c6a20302d5 Added better logging
Windel Bouwman
parents: 252
diff changeset
20 def onFunction(self, f):
74c6a20302d5 Added better logging
Windel Bouwman
parents: 252
diff changeset
21 """ Override this virtual method """
74c6a20302d5 Added better logging
Windel Bouwman
parents: 252
diff changeset
22 raise NotImplementedError()
74c6a20302d5 Added better logging
Windel Bouwman
parents: 252
diff changeset
23
74c6a20302d5 Added better logging
Windel Bouwman
parents: 252
diff changeset
24 def prepare(self):
74c6a20302d5 Added better logging
Windel Bouwman
parents: 252
diff changeset
25 pass
173
c1d2b6b9f9a7 Rework into passes
Windel Bouwman
parents:
diff changeset
26
240
6259856841a0 Remove project
Windel Bouwman
parents: 239
diff changeset
27
173
c1d2b6b9f9a7 Rework into passes
Windel Bouwman
parents:
diff changeset
28 class BasicBlockPass(FunctionPass):
240
6259856841a0 Remove project
Windel Bouwman
parents: 239
diff changeset
29 def onFunction(self, f):
274
ea93e0a7a31e Move docs
Windel Bouwman
parents: 261
diff changeset
30 for bb in f.Blocks:
240
6259856841a0 Remove project
Windel Bouwman
parents: 239
diff changeset
31 self.onBasicBlock(bb)
6259856841a0 Remove project
Windel Bouwman
parents: 239
diff changeset
32
6259856841a0 Remove project
Windel Bouwman
parents: 239
diff changeset
33 def onBasicBlock(self, bb):
6259856841a0 Remove project
Windel Bouwman
parents: 239
diff changeset
34 """ Override this virtual method """
6259856841a0 Remove project
Windel Bouwman
parents: 239
diff changeset
35 raise NotImplementedError()
6259856841a0 Remove project
Windel Bouwman
parents: 239
diff changeset
36
6259856841a0 Remove project
Windel Bouwman
parents: 239
diff changeset
37
173
c1d2b6b9f9a7 Rework into passes
Windel Bouwman
parents:
diff changeset
38 class InstructionPass(BasicBlockPass):
240
6259856841a0 Remove project
Windel Bouwman
parents: 239
diff changeset
39 def onBasicBlock(self, bb):
6259856841a0 Remove project
Windel Bouwman
parents: 239
diff changeset
40 for ins in iter(bb.Instructions):
6259856841a0 Remove project
Windel Bouwman
parents: 239
diff changeset
41 self.onInstruction(ins)
6259856841a0 Remove project
Windel Bouwman
parents: 239
diff changeset
42
6259856841a0 Remove project
Windel Bouwman
parents: 239
diff changeset
43 def onInstruction(self, ins):
6259856841a0 Remove project
Windel Bouwman
parents: 239
diff changeset
44 """ Override this virtual method """
6259856841a0 Remove project
Windel Bouwman
parents: 239
diff changeset
45 raise NotImplementedError()
173
c1d2b6b9f9a7 Rework into passes
Windel Bouwman
parents:
diff changeset
46
280
02385f62f250 Rework from str interface to Instruction interface
Windel Bouwman
parents: 279
diff changeset
47
279
2ccd57b1d78c Fix register allocator to do burn2 OK
Windel Bouwman
parents: 274
diff changeset
48 class BasePass(BasicBlockPass):
255
7416c923a02a Added more logging
Windel Bouwman
parents: 253
diff changeset
49 def onBasicBlock(self, bb):
279
2ccd57b1d78c Fix register allocator to do burn2 OK
Windel Bouwman
parents: 274
diff changeset
50 pass
2ccd57b1d78c Fix register allocator to do burn2 OK
Windel Bouwman
parents: 274
diff changeset
51
280
02385f62f250 Rework from str interface to Instruction interface
Windel Bouwman
parents: 279
diff changeset
52
279
2ccd57b1d78c Fix register allocator to do burn2 OK
Windel Bouwman
parents: 274
diff changeset
53 # Usefull transforms:
2ccd57b1d78c Fix register allocator to do burn2 OK
Windel Bouwman
parents: 274
diff changeset
54 class ConstantFolder(BasePass):
2ccd57b1d78c Fix register allocator to do burn2 OK
Windel Bouwman
parents: 274
diff changeset
55 def __init__(self):
2ccd57b1d78c Fix register allocator to do burn2 OK
Windel Bouwman
parents: 274
diff changeset
56 super().__init__()
2ccd57b1d78c Fix register allocator to do burn2 OK
Windel Bouwman
parents: 274
diff changeset
57 self.ops = {}
2ccd57b1d78c Fix register allocator to do burn2 OK
Windel Bouwman
parents: 274
diff changeset
58 self.ops['+'] = lambda x, y: x + y
2ccd57b1d78c Fix register allocator to do burn2 OK
Windel Bouwman
parents: 274
diff changeset
59 self.ops['-'] = lambda x, y: x - y
2ccd57b1d78c Fix register allocator to do burn2 OK
Windel Bouwman
parents: 274
diff changeset
60 self.ops['*'] = lambda x, y: x * y
2ccd57b1d78c Fix register allocator to do burn2 OK
Windel Bouwman
parents: 274
diff changeset
61 self.ops['<<'] = lambda x, y: x << y
2ccd57b1d78c Fix register allocator to do burn2 OK
Windel Bouwman
parents: 274
diff changeset
62
2ccd57b1d78c Fix register allocator to do burn2 OK
Windel Bouwman
parents: 274
diff changeset
63 def postExpr(self, expr):
2ccd57b1d78c Fix register allocator to do burn2 OK
Windel Bouwman
parents: 274
diff changeset
64 if type(i) is BinaryOperator and i.operation in self.ops.keys() and type(i.a) is Const and type(i.b) is Const:
280
02385f62f250 Rework from str interface to Instruction interface
Windel Bouwman
parents: 279
diff changeset
65 vr = self.ops[i.operation](i.a.value, i.b.value)
279
2ccd57b1d78c Fix register allocator to do burn2 OK
Windel Bouwman
parents: 274
diff changeset
66 return Const(vr)
2ccd57b1d78c Fix register allocator to do burn2 OK
Windel Bouwman
parents: 274
diff changeset
67 else:
2ccd57b1d78c Fix register allocator to do burn2 OK
Windel Bouwman
parents: 274
diff changeset
68 return expr
237
81752b0f85a5 Added burn led test program
Windel Bouwman
parents: 235
diff changeset
69
81752b0f85a5 Added burn led test program
Windel Bouwman
parents: 235
diff changeset
70
174
3eb06f5fb987 Added memory alloc for locals
Windel Bouwman
parents: 173
diff changeset
71 class DeadCodeDeleter(BasicBlockPass):
252
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
72 def onBasicBlock(self, bb):
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
73 def instructionUsed(ins):
253
74c6a20302d5 Added better logging
Windel Bouwman
parents: 252
diff changeset
74 if not type(ins) in [ImmLoad, BinaryOperator]:
74c6a20302d5 Added better logging
Windel Bouwman
parents: 252
diff changeset
75 return True
252
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
76 if len(ins.defs) == 0:
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
77 # In case this instruction does not define any
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
78 # variables, assume it is usefull.
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
79 return True
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
80 return any(d.Used for d in ins.defs)
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
81
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
82 change = True
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
83 while change:
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
84 change = False
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
85 for i in bb.Instructions:
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
86 if instructionUsed(i):
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
87 continue
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
88 bb.removeInstruction(i)
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
89 change = True
173
c1d2b6b9f9a7 Rework into passes
Windel Bouwman
parents:
diff changeset
90
239
63bb40758066 added check
Windel Bouwman
parents: 237
diff changeset
91
252
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
92 class CommonSubexpressionElimination(BasicBlockPass):
239
63bb40758066 added check
Windel Bouwman
parents: 237
diff changeset
93 def onBasicBlock(self, bb):
63bb40758066 added check
Windel Bouwman
parents: 237
diff changeset
94 constMap = {}
252
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
95 to_remove = []
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
96 for i in bb.Instructions:
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
97 if isinstance(i, ImmLoad):
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
98 if i.value in constMap:
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
99 t_new = constMap[i.value]
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
100 t_old = i.target
253
74c6a20302d5 Added better logging
Windel Bouwman
parents: 252
diff changeset
101 logging.debug('Replacing {} with {}'.format(t_old, t_new))
261
444b9df2ed99 try to split up code generation
Windel Bouwman
parents: 255
diff changeset
102 t_old.replaceby(t_new)
252
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
103 to_remove.append(i)
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
104 else:
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
105 constMap[i.value] = i.target
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
106 elif isinstance(i, BinaryOperator):
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
107 k = (i.value1, i.operation, i.value2)
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
108 if k in constMap:
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
109 t_old = i.result
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
110 t_new = constMap[k]
253
74c6a20302d5 Added better logging
Windel Bouwman
parents: 252
diff changeset
111 logging.debug('Replacing {} with {}'.format(t_old, t_new))
261
444b9df2ed99 try to split up code generation
Windel Bouwman
parents: 255
diff changeset
112 t_old.replaceby(t_new)
252
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
113 to_remove.append(i)
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
114 else:
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
115 constMap[k] = i.result
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
116 for i in to_remove:
316
56e6ff84f646 Fixed burn led demo
Windel Bouwman
parents: 301
diff changeset
117 self.logger.debug('removing {}'.format(i))
252
c4370696ccc7 added optimize function
Windel Bouwman
parents: 240
diff changeset
118 bb.removeInstruction(i)
240
6259856841a0 Remove project
Windel Bouwman
parents: 239
diff changeset
119
317
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
120 class RemoveAddZero(InstructionPass):
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
121 def onInstruction(self, i):
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
122 if type(i) is ir.Binop:
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
123 print(i)
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
124 pass
240
6259856841a0 Remove project
Windel Bouwman
parents: 239
diff changeset
125
177
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 176
diff changeset
126 class CleanPass(FunctionPass):
219
1fa3e0050b49 Expanded ad hoc code generator
Windel Bouwman
parents: 177
diff changeset
127 def onFunction(self, f):
316
56e6ff84f646 Fixed burn led demo
Windel Bouwman
parents: 301
diff changeset
128 self.remove_empty_blocks(f)
317
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
129 self.remove_one_preds(f)
280
02385f62f250 Rework from str interface to Instruction interface
Windel Bouwman
parents: 279
diff changeset
130
316
56e6ff84f646 Fixed burn led demo
Windel Bouwman
parents: 301
diff changeset
131 def remove_empty_blocks(self, f):
56e6ff84f646 Fixed burn led demo
Windel Bouwman
parents: 301
diff changeset
132 """ Remove empty basic blocks from function. """
56e6ff84f646 Fixed burn led demo
Windel Bouwman
parents: 301
diff changeset
133 # If a block only contains a branch, it can be removed:
56e6ff84f646 Fixed burn led demo
Windel Bouwman
parents: 301
diff changeset
134 empty = lambda b: type(b.FirstInstruction) is ir.Jump
56e6ff84f646 Fixed burn led demo
Windel Bouwman
parents: 301
diff changeset
135 empty_blocks = list(filter(empty, f.Blocks))
56e6ff84f646 Fixed burn led demo
Windel Bouwman
parents: 301
diff changeset
136 for b in empty_blocks:
56e6ff84f646 Fixed burn led demo
Windel Bouwman
parents: 301
diff changeset
137 # Update predecessors
56e6ff84f646 Fixed burn led demo
Windel Bouwman
parents: 301
diff changeset
138 preds = b.Predecessors
56e6ff84f646 Fixed burn led demo
Windel Bouwman
parents: 301
diff changeset
139 if b not in preds + [f.entry]:
56e6ff84f646 Fixed burn led demo
Windel Bouwman
parents: 301
diff changeset
140 # Do not remove if preceeded by itself
56e6ff84f646 Fixed burn led demo
Windel Bouwman
parents: 301
diff changeset
141 tgt = b.LastInstruction.target
56e6ff84f646 Fixed burn led demo
Windel Bouwman
parents: 301
diff changeset
142 for pred in preds:
56e6ff84f646 Fixed burn led demo
Windel Bouwman
parents: 301
diff changeset
143 pred.LastInstruction.changeTarget(b, tgt)
56e6ff84f646 Fixed burn led demo
Windel Bouwman
parents: 301
diff changeset
144 self.logger.debug('Removing empty block: {}'.format(b))
56e6ff84f646 Fixed burn led demo
Windel Bouwman
parents: 301
diff changeset
145 f.removeBlock(b)
317
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
146
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
147 def remove_one_preds(self, f):
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
148 """ Remove basic blocks with only one predecessor """
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
149 change = True
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
150 while change:
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
151 change = False
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
152 for block in f.Blocks:
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
153 preds = block.Predecessors
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
154 if len(preds) == 1 and block not in preds and type(preds[0].LastInstruction) is ir.Jump and block is not f.epiloog:
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
155 self.glue_blocks(preds[0], block, f)
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
156 change = True
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
157
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
158 def glue_blocks(self, block1, block2, f):
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
159 """ Glue two blocks together into the first block """
334
6f4753202b9a Added more recipes
Windel Bouwman
parents: 317
diff changeset
160 self.logger.debug('Glueing {} and {}'.format(block1, block2))
317
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
161
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
162 # Remove the last jump:
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
163 block1.removeInstruction(block1.LastInstruction)
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
164
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
165 # Copy all instructions to block1:
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
166 for instruction in block2.Instructions:
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
167 block1.addInstruction(instruction)
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
168 # This does not work somehow:
e30a77ae359b Added glue blocks
Windel Bouwman
parents: 316
diff changeset
169 #block2.parent.removeBlock(block2)