annotate python/ppci/transform.py @ 345:b4882ff0ed06

Added more arm isa tests
author Windel Bouwman
date Sun, 02 Mar 2014 17:12:08 +0100
parents d1ecc493384e
children c2ddc8a36f5e
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 """
336
d1ecc493384e Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents: 334
diff changeset
160 self.logger.debug('Merging {} and {}'.format(block1.name, block2.name))
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)