forked from sampsyo/bril
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathself_lvn.py
158 lines (147 loc) · 5.07 KB
/
self_lvn.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import sys
import json
from form_blocks import form_blocks
# Some Utility functions and constants
# OP Utils
_COMP_OP_PROP = {
'add':{
'commutative': True,
'foldable': True,
'get_fold_value': lambda a, b: a + b,
},
'mul':{
'commutative': True,
'foldable': True,
'get_fold_value': lambda a, b: a * b,
},
'sub':{
'commutative': False,
'foldable': True,
'get_fold_value': lambda a, b: a - b,
},
'div':{
'commutative': False,
'foldable': True,
'get_fold_value': lambda a, b: a // b,
},
'gt':{
'commutative': False,
'foldable': True,
'get_fold_value': lambda a, b: a > b,
},
'lt':{
'commutative': False,
'foldable': True,
'get_fold_value': lambda a, b: a < b,
},
'ge':{
'commutative': False,
'foldable': True,
'get_fold_value': lambda a, b: a >= b,
},
'le':{
'commutative': False,
'foldable': True,
'get_fold_value': lambda a, b: a <= b,
},
'eq':{
'commutative': True,
'foldable': True,
'get_fold_value': lambda a, b: a == b,
},
'ne':{
'commutative': True,
'foldable': True,
'get_fold_value': lambda a, b: a != b,
},
'or':{
'commutative': True,
'foldable': True,
'get_fold_value': lambda a, b: a or b,
},
'and':{
'commutative': True,
'foldable': True,
'get_fold_value': lambda a, b: a and b,
},
'not':{
'commutative': False,
'foldable': True,
'get_fold_value': lambda a: not a,
},
}
# Var Utils
_var_counts = 0
def _create_canonicalized_var():
global _var_counts
_var_counts += 1
return "_var_" + str(_var_counts)
# Value tuple Utils
def _convert_to_value_tuple(inst, var_to_canonicalized_var):
if 'op' in inst and inst['op'] == 'const':
return ('const', (inst['value']))
if 'op' in inst and 'args' in inst:
return (inst['op'], tuple(var_to_canonicalized_var[v] for v in inst['args']))
return None
# Canonicalization
def canonicalize(block):
for inst in block:
if 'args' in inst:
inst['args'] = sorted(inst['args'])
# Actual LVN stuff
def lvn(block, value_propagation_on, value_tuple_to_canonicalized_var, var_to_canonicalized_var):
for inst in block:
value_tuple = _convert_to_value_tuple(inst, var_to_canonicalized_var)
if value_tuple is None:
continue
if value_propagation_on:
if value_tuple in value_tuple_to_canonicalized_var:
canonicalized_var = value_tuple_to_canonicalized_var[value_tuple]
else:
canonicalized_var = _create_canonicalized_var()
else:
canonicalized_var = _create_canonicalized_var()
if 'dest' in inst:
var_to_canonicalized_var[inst['dest']] = canonicalized_var
inst['dest'] = canonicalized_var
if 'args' in inst:
inst['args'] = list(v for v in value_tuple[1]) #[1] is canonicalized_var of args
value_tuple_to_canonicalized_var[value_tuple] = canonicalized_var
# Constant Folding:
def constant_folding(block, canonicalized_var_to_computed_value):
for inst in block:
if 'op' in inst and inst['op'] == 'const':
canonicalized_var_to_computed_value[inst['dest']] = inst['value']
if 'op' in inst and inst['op'] in _COMP_OP_PROP:
all_const_resolved = True
for arg in inst['args']:
if arg not in canonicalized_var_to_computed_value:
all_const_resolved = False
break
if all_const_resolved:
op = _COMP_OP_PROP[inst['op']]['get_fold_value']
args = tuple(canonicalized_var_to_computed_value[arg] for arg in inst['args'])
if op == 'not':
canonicalized_var_to_computed_value[inst['dest']] = op(args[0])
else:
canonicalized_var_to_computed_value[inst['dest']] = op(args[0], args[1])
inst['op'] = 'const'
inst['type'] = 'int'
del inst['args']
inst['value'] = canonicalized_var_to_computed_value[inst['dest']]
if __name__ == '__main__':
program = json.load(sys.stdin)
for func in program["functions"]:
value_tuple_to_canonicalized_var = {}
var_to_canonicalized_var = {}
blocks = list(form_blocks(func['instrs']))
for block in blocks:
# Preprocess before LVN
if '-c' in sys.argv:
canonicalize(block)
# LVN, including value_propagation
lvn(block, '-p' in sys.argv, value_tuple_to_canonicalized_var, var_to_canonicalized_var)
canonicalized_var_to_computed_value = {}
for block in blocks:
if '-f' in sys.argv:
constant_folding(block, canonicalized_var_to_computed_value)