blob: 632b5f74f654465f74c6ae9426f03459a9e1c6e4 (
plain) (
blame)
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
|
P-Code optimizations:
Let <push-ops> be oPUSH|oPUSHB
Let <load-ops> be oLOD|oLODB|PUSH|oLADR|oLCADR
pcopt.c:unaryOptimize
STEP 1:
Remove unary operators on constants:
<push-op> arg + oNEG -> <push-op> arg
<push-op> arg + oABS -> <push-op> |arg|
<push-op> arg + oINC -> <push-op> arg+1
<push-op> arg + oDEC -> <push-op> arg-1
<push-op> arg + oNOT -> <push-op> ~arg
Simplify binary operations on constants
<push-op> arg + oADD
if arg == 0 -> delete both
else if arg == 1 -> oINC
else if arg == -1 -> oDEC
<push-op> arg + oSUB
if arg == 0 -> delete both
else if arg == 1 -> oDEC
else if arg == -1 -> oINC
<push-op> arg + oMUL
if arg is power of 2 -> oSLL power
<push-op> arg + oDIV
if arg is power of 2 -> oSRA power
<push-op> arg + oSLL
if arg is 0 -> <push-op> arg
<push-op> arg + oSRL
if arg is 0 -> <push-op> arg
<push-op> arg + oSRA
if arg is 0 -> <push-op> arg
<push-op> arg + oOR
if arg is 0 -> <push-op> arg
<push-op> arg + oAND
if arg is 0xffff -> <push-op> arg
Delete comparisons with zero
<push-op> arg + oEQUZ
if arg == 0 -> <push-op> true
else -> <push-op> false
<push-op> arg + oNEQZ
if arg != 0 -> <push-op> true
else -> <push-op> false
<push-op> arg + oLTZ
if arg < 0 -> <push-op> true
else -> <push-op> false
<push-op> arg + oGTEZ
if arg >= 0 -> <push-op> true
else -> <push-op> false
<push-op> arg + oGTZ
if arg > 0 -> <push-op> true
else -> <push-op> false
<push-op> arg + oLTEZ
if arg <= 0 -> <push-op> true
else -> <push-op> false
Simplify comparisons with certain constants
<push-op> arg + oEQU
if arg == 0 -> oEQUZ
else if arg == 1 -> oDEC + oEQUZ
else if arg == -1 -> oINC + oEQUZ
<push-op> arg + oNEQ
if arg == 0 -> oNEQZ
else if arg == 1 -> oDEC + oNEQZ
else if arg == -1 -> oINC + oNEQZ
<push-op> arg + oLT
if arg == 0 -> oLTZ
else if arg == 1 -> oDEC + oLTZ
else if arg == -1 -> oINC + oLTZ
<push-op> arg + oGTE
if arg == 0 -> oGTEZ
else if arg == 1 -> oDEC + oGTEZ
else if arg == -1 -> oINC + oGTEZ
<push-op> arg + oGT
if arg == 0 -> oGTZ
else if arg == 1 -> oDEC + oGTZ
else if arg == -1 -> oINC + oGTZ
<push-op> arg + oLTE
if arg == 0 -> oLTEZ
else if arg == 1 -> oDEC + oLTEZ
else if arg == -1 -> oINC + oLTEZ
Simplify or delete condition branches on constants
<push-op> arg + oJEQUZ
if arg == 0 -> oJMP
else -> delete both
<push-op> arg + oJNEQZ
if arg != 0 -> oJMP
else -> delete both
<push-op> arg + oJLTZ
if arg < 0 -> oJMP
else -> delete both
<push-op> arg + oJGTEZ
if arg >= 0 -> oJMP
else -> delete both
<push-op> arg + oJGTZ
if arg > 0 -> oJMP
else -> delete both
<push-op> arg + oJLTEZ
if arg <= 0 -> oJMP
else -> delete both
STEP 1a:
<push-op> arg
if arg < 256 -> oPUSHB arg
else -> oPUSH arg
STEP 2:
Delete multiple modifications of DSEG pointer
INDS arg1 + INDS arg2 -> INDS arg1+arg2
pcopt.c:binaryOptimize
STEP 1:
<push-op> arg1 + <push-op> arg2 + oADD -> oPUSH arg1 + arg2 + STEP 1a
<push-op> arg1 + <push-op> arg2 + oSUB -> oPUSH arg1 - arg2 + STEP 1a
<push-op> arg1 + <push-op> arg2 + oMUL -> oPUSH arg1 * arg2 + STEP 1a
<push-op> arg1 + <push-op> arg2 + oDIV -> oPUSH arg1 / arg2 + STEP 1a
<push-op> arg1 + <push-op> arg2 + oMOD -> oPUSH arg1 % arg2 + STEP 1a
<push-op> arg1 + <push-op> arg2 + oSLL -> oPUSH arg1 << arg2 + STEP 1a
<push-op> arg1 + <push-op> arg2 + oSRL -> oPUSH arg1 >> arg2 + STEP 1a
<push-op> arg1 + <push-op> arg2 + oSRA -> oPUSH arg1 >> arg2 + STEP 1a
<push-op> arg1 + <push-op> arg2 + oOR -> oPUSH arg1 | arg2 + STEP 1a
<push-op> arg1 + <push-op> arg2 + oAND -> oPUSH arg1 & arg2 + STEP 1a
<push-op> arg1 + <push-op> arg2 + oEQU -> oPUSH arg1 == arg2 + STEP 1a
<push-op> arg1 + <push-op> arg2 + oNEQ -> oPUSH arg1 != arg2 + STEP 1a
<push-op> arg1 + <push-op> arg2 + oLT -> oPUSH arg1 < arg2 + STEP 1a
<push-op> arg1 + <push-op> arg2 + oGTE -> oPUSH arg1 >= arg2 + STEP 1a
<push-op> arg1 + <push-op> arg2 + oGT -> oPUSH arg1 > arg2 + STEP 1a
<push-op> arg1 + <push-op> arg2 + oLTE -> oPUSH arg1 <= arg2 + STEP 1a
STEP 1a:
<push-op> arg
if arg < 256 -> oPUSHB arg
else -> oPUSH arg
STEP 2:
<push-op> arg1 + <load-ops> arg2 + oADD
if arg1 == 0 -> <load-ops> arg
else if arg1 == 1 -> <load-ops> arg + oINC
else if arg1 == -1 -> <load-ops> arg + oDEC
<push-op> arg1 + <load-ops> arg2 + oSUB
if arg1 == 0 -> <load-ops> arg + oNEG
<push-op> arg1 + <load-ops> arg2 + oMUL -> <load-ops> arg + oSLL log
if arg is a power of 2
<push-op> arg1 + <load-ops> arg2 + oOR
if arg1 == 0 -> <load-ops> arg
<push-op> arg1 + <load-ops> arg2 + oAND
if arg1 == 0xffff -> <load-ops> arg
<push-op> arg1 + <load-ops> arg2 + oEQU
if arg1 == 0 -> <load-ops> arg + oEQUZ
<push-op> arg1 + <load-ops> arg2 + oNEQ
if arg1 == 0 -> <load-ops> arg + oNEQZ
<push-op> arg1 + <load-ops> arg2 + oLT
if arg1 == 0 -> <load-ops> arg + oLTZ
<push-op> arg1 + <load-ops> arg2 + oGTE
if arg1 == 0 -> <load-ops> arg + oGTEZ
<push-op> arg1 + <load-ops> arg2 + oGT
if arg1 == 0 -> <load-ops> arg + oGTZ
<push-op> arg1 + <load-ops> arg2 + oLTE
if arg1 == 0 -> <load-ops> arg + oLTEZ
STEP 2a:
if the <push-op> op is still there
<push-op> arg
if arg < 256 -> oPUSHB arg
else -> oPUSH arg
STEP 3
oNEG + oADD -> oSUB
oNEG + oSUB -> oADD
pjopt.c: BranchOptimize
oNOT + oJEQUZ -> oJNEQZ
oNOT + oJNEQZ -> oJEQUZ
oNEG + oJLTZ -> oJGTZ
oNEG + oJGTEZ -> oJLTEZ
oNEG + oJGTZ -> oJLTZ
oNEG + oJLTEZ -> oJGTEZ
oEQU + oNOT -> oNEQ
oEQU + oJEQUZ -> oJNEQ
oEQU + oJNEQZ -> oJEQU
oNEQ + oNOT -> oEQU
oNEQ + oJEQUZ -> oJEQU
oNEQ + oJNEQZ -> oJNEQ
oLT + oNOT -> oGTE
oLT + oJEQUZ -> oJGTE
oLT + oJNEQZ -> oJLT
oGTE + oNOT -> oLT
oGTE + oJEQUZ -> oJLT
oGTE + oJNEQZ -> oJGTE
oGT + oNOT -> oLTE
oGT + oJEQUZ -> oJLTE
oGT + oJNEQZ -> oJGT
oLTE + oJNOT -> oGT
oLTE + oJEQUZ -> oJGT
oLTE + oJNEQZ -> oJLTE
oEQUZ + oNOT -> oNEQZ
oEQUZ + oJEQUZ -> oJNEQZ
oEQUZ + oJNEQZ -> oJEQUZ
oNEQZ + oNOT -> oEQUZ
oNEQZ + oJEQUZ -> oJEQUZ
oNEQZ + oJNEQZ -> oJNEQZ
oLTZ + oNOT -> oGTEZ
oLTZ + oJEQUZ -> oJGTEZ
oLTZ + oJNEQZ -> oJLTZ
oGTEZ + oNOT -> oLTZ
oGTEZ + oJEQUZ -> oJLTZ
oGTEZ + oJNEQZ -> oJGTEZ
oGTZ + oNOT -> oLTEZ
oGTZ + oJEQUZ -> oJLTEZ
oGTZ + oJNEQZ -> oJGTZ
oLTEZ + oNOT -> oGTZ
oLTEZ + oJEQUZ -> oJGTZ
oLTEZ + oJNEQZ -> oJLTEZ
plopt.c:LoadOptimize()
Eliminate duplicate loads
oLOD arg1 + oLOAD arg1 -> oLOD arg1 + oDUP
Convert loads indexed by a constant to unindexed loads
!!! DISABLED !!! Does not work because arg2 is a label, not an address !!!
<push-op> arg1 + oLODX arg2 -> oLOD arg1 + arg2
<push-op> arg1 + oLADRX arg2 -> oLADR arg1 + arg2
<push-op> arg1 + oLODBX arg2 -> oLODB arg1 + arg2
<push-op> arg1 + oLODMX arg2 -> oLODM arg1 + arg2
<push-op> arg
if arg < 256 -> oPUSHB arg
plopt.c:StoreOptimize()
Eliminate store followed by load
oSTO arg + oLOAD arg -> oSTO arg + oDUP
Convert stores indexed by a constant to unindexed stores
<push-op> arg1 + ? + oSTOX arg2 -> ? + oSTO arg1 + arg2
<push-op> arg1 + ? + oSTOBX arg2 -> ? + oSTOB arg1 + arg2
Missing local optimization:
Need to check for branches (conditional or unconditional) to the
next instruction.
|