173
|
1 from ir import *
|
|
2 # Standard passes:
|
|
3
|
|
4 class FunctionPass:
|
|
5 def run(self, ir):
|
|
6 """ Main entry point for the pass """
|
|
7 for f in ir.Functions:
|
|
8 self.onFunction(f)
|
|
9 def onFunction(self, f):
|
|
10 """ Override this virtual method """
|
|
11 raise NotImplementedError()
|
|
12
|
|
13 class BasicBlockPass(FunctionPass):
|
|
14 def onFunction(self, f):
|
|
15 for bb in f.BasicBlocks:
|
|
16 self.onBasicBlock(bb)
|
|
17 def onBasicBlock(self, bb):
|
|
18 """ Override this virtual method """
|
|
19 raise NotImplementedError()
|
|
20
|
|
21 class InstructionPass(BasicBlockPass):
|
|
22 def onBasicBlock(self, bb):
|
174
|
23 for ins in iter(bb.Instructions):
|
173
|
24 self.onInstruction(ins)
|
|
25 def onInstruction(self, ins):
|
|
26 """ Override this virtual method """
|
|
27 raise NotImplementedError()
|
|
28
|
|
29 # Usefull transforms:
|
|
30 class ConstantFolder(InstructionPass):
|
|
31 def onInstruction(self, i):
|
|
32 if type(i) is ImmLoad:
|
|
33 i.target.constval = i.value
|
|
34 elif type(i) is BinaryOperator:
|
|
35 a = i.value1
|
|
36 b = i.value2
|
|
37 if hasattr(a, 'constval') and hasattr(b,'constval'):
|
|
38 op = i.operation
|
|
39 if op == '+':
|
|
40 i2 = ImmLoad(i.result, a.constval + b.constval)
|
|
41 i.Parent.replaceInstruction(i, i2)
|
|
42 elif op == '*':
|
|
43 i2 = ImmLoad(i.result, a.constval * b.constval)
|
|
44 i.Parent.replaceInstruction(i, i2)
|
|
45 elif op == '-':
|
|
46 i2 = ImmLoad(i.result, a.constval - b.constval)
|
|
47 i.Parent.replaceInstruction(i, i2)
|
|
48
|
174
|
49 class DeadCodeDeleter(BasicBlockPass):
|
|
50 def onBasicBlock(self, bb):
|
|
51 def instructionUsed(ins):
|
|
52 if len(ins.defs) == 0:
|
|
53 # In case this instruction does not define any variables, assume it is usefull.
|
|
54 return True
|
|
55 for d in ins.defs:
|
|
56 if d.IsUsed:
|
|
57 return True
|
|
58 return False
|
|
59 bb.Instructions = list(filter(instructionUsed, bb.Instructions))
|
173
|
60
|
175
|
61 def isAllocPromotable(allocinst):
|
|
62 # Check if alloc value is only used by load and store operations.
|
|
63 assert type(allocinst) is Alloc
|
|
64 for use in ai.value.used_by:
|
|
65 print(use.user, use)
|
|
66 if not type(use.user) in [Load, Store]:
|
|
67 # TODO: check volatile
|
|
68 return False
|
|
69 otherUse = True
|
|
70 return True
|
|
71
|
|
72 class Mem2RegPromotor(FunctionPass):
|
|
73 def onFunction(self, f):
|
|
74 print(f)
|
|
75
|