00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 #include "wsint.h"
00071 #include "wsasm.h"
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 static WsBool opt_jumps_to_jumps(WsCompilerPtr compiler)
00082 {
00083 WsAsmIns *i;
00084 WsBool change = WS_TRUE;
00085 unsigned int count = 0;
00086
00087 ws_info(compiler, "optimize: jumps to jumps");
00088
00089 while (change) {
00090 count++;
00091 change = WS_FALSE;
00092
00093 for (i = compiler->asm_head; i; i = i->next) {
00094 WsAsmIns * j;
00095
00096 if (!WS_ASM_P_BRANCH(i))
00097 continue;
00098
00099
00100 for (j = i->ws_label; j && j->type == WS_ASM_P_LABEL; j = j->next)
00101 ;
00102
00103 if (j == NULL || j->type != WS_ASM_P_JUMP)
00104
00105 continue;
00106
00107
00108
00109
00110
00111 i->ws_label->ws_label_refcount--;
00112 j->ws_label->ws_label_refcount++;
00113
00114 i->ws_label = j->ws_label;
00115 change = WS_TRUE;
00116 }
00117 }
00118
00119 return count > 1;
00120 }
00121
00122
00123 static WsBool opt_jumps_to_next_instruction(WsCompilerPtr compiler)
00124 {
00125 WsAsmIns *i;
00126 WsBool change = WS_FALSE;
00127
00128 ws_info(compiler, "optimize: jumps to next instruction");
00129
00130 for (i = compiler->asm_head; i; i = i->next) {
00131 WsAsmIns * j;
00132
00133 if (i->type != WS_ASM_P_JUMP)
00134 continue;
00135
00136 for (j = i->next;
00137 j && j->type == WS_ASM_P_LABEL && i->ws_label != j;
00138 j = j->next)
00139 ;
00140
00141 if (i->ws_label != j)
00142
00143 continue;
00144
00145
00146
00147 change = WS_TRUE;
00148 i->ws_label->ws_label_refcount--;
00149
00150 if (i->next)
00151 i->next->prev = i->prev;
00152 else
00153 compiler->asm_tail = i->prev;
00154
00155 if (i->prev)
00156 i->prev->next = i->next;
00157 else
00158 compiler->asm_head = i->next;
00159
00160
00161 i = j;
00162 }
00163
00164 return change;
00165 }
00166
00167
00168 static WsBool opt_dead_code(WsCompilerPtr compiler)
00169 {
00170 WsBool change = WS_FALSE;
00171 WsAsmIns *i;
00172
00173 ws_info(compiler, "optimize: dead code");
00174
00175 for (i = compiler->asm_head; i; i = i->next) {
00176 WsAsmIns * j;
00177
00178 if (!(i->type == WS_ASM_P_JUMP ||
00179 i->type == WS_ASM_RETURN ||
00180 i->type == WS_ASM_RETURN_ES))
00181 continue;
00182
00183
00184 for (j = i->next;
00185 j && (j->type != WS_ASM_P_LABEL || j->ws_label_refcount == 0);
00186 j = j->next) {
00187
00188 if (WS_ASM_P_BRANCH(j))
00189 j->ws_label->ws_label_refcount--;
00190 }
00191
00192 if (j == i->next)
00193
00194 continue;
00195
00196
00197 i->next = j;
00198 if (j)
00199 j->prev = i;
00200 else
00201 compiler->asm_tail = i;
00202
00203 change = WS_TRUE;
00204 }
00205
00206 return change;
00207 }
00208
00209
00210 static WsBool opt_peephole(WsCompilerPtr compiler)
00211 {
00212 WsBool change = WS_FALSE;
00213 WsAsmIns *i, *i2, *prev;
00214 WsAsmIns *new;
00215
00216 ws_info(compiler, "optimize: peephole");
00217
00218 prev = NULL;
00219 i = compiler->asm_head;
00220 while (i) {
00221
00222 if (i->next) {
00223 i2 = i->next;
00224
00225
00226
00227
00228
00229 if (i2->type == WS_ASM_POP
00230 && (i->type == WS_ASM_P_LOAD_VAR
00231 || i->type == WS_ASM_P_LOAD_CONST
00232 || i->type == WS_ASM_CONST_0
00233 || i->type == WS_ASM_CONST_1
00234 || i->type == WS_ASM_CONST_M1
00235 || i->type == WS_ASM_CONST_ES
00236 || i->type == WS_ASM_CONST_INVALID
00237 || i->type == WS_ASM_CONST_TRUE
00238 || i->type == WS_ASM_CONST_FALSE)) {
00239
00240 change = WS_TRUE;
00241
00242 if (prev)
00243 prev->next = i2->next;
00244 else
00245 compiler->asm_head = i2->next;
00246
00247 if (i2->next)
00248 i2->next->prev = prev;
00249 else
00250 compiler->asm_tail = prev;
00251
00252 i = i2->next;
00253 continue;
00254 }
00255
00256
00257
00258
00259
00260 if (i2->type == WS_ASM_RETURN && i->type == WS_ASM_CONST_ES) {
00261
00262 new = ws_asm_ins(compiler, i->line, WS_ASM_RETURN_ES);
00263 if (new) {
00264 change = WS_TRUE;
00265
00266 if (prev)
00267 prev->next = new;
00268 else
00269 compiler->asm_head = new;
00270
00271 new->prev = prev;
00272 new->next = i2->next;
00273
00274 if (new->next)
00275 new->next->prev = new;
00276 else
00277 compiler->asm_tail = new;
00278
00279 i = new;
00280 continue;
00281 }
00282 }
00283 }
00284
00285
00286 prev = i;
00287 i = i->next;
00288 }
00289
00290
00291
00292
00293 if (compiler->asm_tail && compiler->asm_tail->type == WS_ASM_RETURN_ES) {
00294 compiler->asm_tail = compiler->asm_tail->prev;
00295 if (compiler->asm_tail == NULL)
00296 compiler->asm_head = NULL;
00297 else
00298 compiler->asm_tail->next = NULL;
00299 }
00300
00301 return change;
00302 }
00303
00304
00305
00306
00307
00308 static WsBool opt_conv(WsCompilerPtr compiler)
00309 {
00310 WsBool change = WS_FALSE;
00311 WsAsmIns *i, *next, *prev;
00312
00313 ws_info(compiler, "optimize: peephole");
00314
00315 prev = NULL;
00316 i = compiler->asm_head;
00317 while (i) {
00318 if (i->type == WS_ASM_TOBOOL) {
00319 next = i->next;
00320
00321
00322
00323 while (next != NULL && next->type == WS_ASM_P_LABEL)
00324 next = next->next;
00325
00326 if (next != NULL &&
00327 (next->type == WS_ASM_P_TJUMP ||
00328 next->type == WS_ASM_NOT ||
00329 next->type == WS_ASM_SCAND ||
00330 next->type == WS_ASM_SCOR ||
00331 next->type == WS_ASM_TOBOOL ||
00332 next->type == WS_ASM_POP)) {
00333
00334
00335
00336 change = WS_TRUE;
00337
00338
00339
00340 if (prev)
00341 prev->next = i->next;
00342 else
00343 compiler->asm_head = i->next;
00344
00345 if (i->next)
00346 i->next->prev = prev;
00347 else
00348 compiler->asm_tail = prev;
00349 }
00350 }
00351
00352 prev = i;
00353 i = i->next;
00354 }
00355
00356 return change;
00357 }
00358
00359
00360
00361
00362 void ws_asm_optimize(WsCompilerPtr compiler)
00363 {
00364 WsBool change = WS_TRUE;
00365
00366
00367
00368 while (change) {
00369 change = WS_FALSE;
00370
00371
00372 if (!compiler->params.no_opt_conv && opt_conv(compiler))
00373 change = WS_TRUE;
00374
00375
00376 if (!compiler->params.no_opt_peephole && opt_peephole(compiler))
00377 change = WS_TRUE;
00378
00379
00380 if (!compiler->params.no_opt_jumps_to_jumps
00381 && opt_jumps_to_jumps(compiler))
00382 change = WS_TRUE;
00383
00384
00385 if (!compiler->params.no_opt_jumps_to_next_instruction
00386 && opt_jumps_to_next_instruction(compiler))
00387 change = WS_TRUE;
00388
00389
00390 if (!compiler->params.no_opt_dead_code && opt_dead_code(compiler))
00391 change = WS_TRUE;
00392 }
00393 }
See file LICENSE for details about the license agreement for using,
modifying, copying or deriving work from this software.