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