253
|
1 import logging
|
|
2 from transform import FunctionPass
|
|
3 from ir import *
|
|
4
|
|
5 def isAllocPromotable(allocinst):
|
|
6 # Check if alloc value is only used by load and store operations.
|
|
7 assert type(allocinst) is Alloc
|
261
|
8 return all(type(use) in [Load, Store] for use in allocinst.value.used_by)
|
253
|
9
|
|
10 class Mem2RegPromotor(FunctionPass):
|
|
11 def promoteSingleBlock(self, ai):
|
|
12 v = ai.value
|
|
13 bb = ai.Block
|
|
14
|
|
15 # Replace all loads with the value:
|
|
16 loads = [i for i in v.used_by if isinstance(i, Load)]
|
|
17 stores = [i for i in v.used_by if isinstance(i, Store)]
|
|
18 stores.sort(key=lambda s: s.Position)
|
|
19 stores.reverse()
|
|
20
|
|
21 for load in loads:
|
|
22 idx = load.Position
|
|
23 # Search upwards:
|
|
24 for store in stores:
|
|
25 if store.Position < load.Position:
|
|
26 break
|
261
|
27 load.value.replaceby(store.value)
|
253
|
28 logging.debug('replaced {} with {}'.format(load, store.value))
|
|
29 bb.removeInstruction(load)
|
|
30
|
|
31 # Remove store instructions:
|
|
32 for store in stores:
|
|
33 sv = store.value
|
|
34 logging.debug('removing {}'.format(store))
|
|
35 bb.removeInstruction(store)
|
|
36 #assert sv.Used
|
|
37
|
|
38 # Remove alloca instruction:
|
|
39 assert not ai.value.Used, ai.value.used_by
|
|
40 bb.removeInstruction(ai)
|
|
41
|
|
42 def promote(self, ai):
|
|
43 # Find load operations and replace them with assignments
|
|
44 v = ai.value
|
|
45 if len(ai.value.UsedInBlocks) == 1:
|
|
46 self.promoteSingleBlock(ai)
|
|
47 return
|
|
48
|
|
49 loads = [i for i in v.used_by if isinstance(i, Load)]
|
|
50 stores = [i for i in v.used_by if isinstance(i, Store)]
|
|
51
|
|
52 # Each store instruction can be removed (later).
|
|
53 # Instead of storing the value, we use it
|
|
54 # where the load would have been!
|
|
55 replMap = {}
|
|
56 for store in stores:
|
|
57 replMap[store] = store.value
|
|
58
|
|
59 # for each load, track back what the defining store
|
|
60 # was.
|
|
61 for load in loads:
|
|
62 pass
|
|
63
|
|
64 def onFunction(self, f):
|
|
65 for bb in f.BasicBlocks:
|
|
66 allocs = [i for i in bb.Instructions if isinstance(i, Alloc)]
|
|
67 for i in allocs:
|
|
68 if isAllocPromotable(i):
|
|
69 self.promote(i)
|
|
70
|