summaryrefslogtreecommitdiff
path: root/misc/pascal/insn16/doc/PascalOptimizations.txt
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.