#include "wsint.h"#include "wsasm.h"Include dependency graph for wsopt.c:

Go to the source code of this file.
Functions | |
| WsBool | opt_jumps_to_jumps (WsCompilerPtr compiler) |
| WsBool | opt_jumps_to_next_instruction (WsCompilerPtr compiler) |
| WsBool | opt_dead_code (WsCompilerPtr compiler) |
| WsBool | opt_peephole (WsCompilerPtr compiler) |
| WsBool | opt_conv (WsCompilerPtr compiler) |
| void | ws_asm_optimize (WsCompilerPtr compiler) |
|
|
Definition at line 308 of file wsopt.c. References WsCompilerRec::asm_head, WsCompilerRec::asm_tail, WsAsmInsRec::next, WsAsmInsRec::prev, WsAsmInsRec::type, WS_ASM_NOT, WS_ASM_P_TJUMP, WS_ASM_SCAND, WS_ASM_SCOR, WS_ASM_TOBOOL, ws_info(), WsAsmIns, WsBool, and WsCompilerPtr. Referenced by ws_asm_optimize(). 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 /* Skip labels. They're not going to affect which instruction
00322 * gets executed after this TOBOOL. */
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 /* The next instruction will automatically convert its
00334 * operand to boolean, or does not care about its operand
00335 * (POP), so the TOBOOL is not necessary. Delete it. */
00336 change = WS_TRUE;
00337
00338 /* Use i->next here because next might have been incremented
00339 * past a label, which we do not want to delete. */
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 }
|
Here is the call graph for this function:

|
|
Definition at line 168 of file wsopt.c. References WsCompilerRec::asm_head, WsCompilerRec::asm_tail, WsAsmInsRec::next, WsAsmInsRec::prev, WsAsmInsRec::type, WS_ASM_P_BRANCH, WS_ASM_P_JUMP, WS_ASM_P_LABEL, WS_ASM_RETURN, ws_info(), WsAsmIns, WsBool, and WsCompilerPtr. Referenced by ws_asm_optimize(). 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 /* Skip until the next referenced label is found. */
00184 for (j = i->next;
00185 j && (j->type != WS_ASM_P_LABEL || j->ws_label_refcount == 0);
00186 j = j->next) {
00187 /* Update label reference counts in the deleted block. */
00188 if (WS_ASM_P_BRANCH(j))
00189 j->ws_label->ws_label_refcount--;
00190 }
00191
00192 if (j == i->next)
00193 /* Nothing to delete. */
00194 continue;
00195
00196 /* Delete everything between `i' and `j'. */
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 }
|
Here is the call graph for this function:

|
|
Definition at line 81 of file wsopt.c. References WsCompilerRec::asm_head, WsAsmInsRec::next, WsAsmInsRec::type, WS_ASM_P_BRANCH, ws_info(), WsAsmIns, WsBool, and WsCompilerPtr. Referenced by ws_asm_optimize(). 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 /* Find the next instruction following the label. */
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 /* Can't optimize this case. */
00105 continue;
00106
00107 /* We can optimize the jump `i' directly to the label of
00108 `j'. We must remember to update the reference counts
00109 too. */
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 }
|
Here is the call graph for this function:

|
|
Definition at line 123 of file wsopt.c. References WsCompilerRec::asm_head, WsCompilerRec::asm_tail, WsAsmInsRec::next, WsAsmInsRec::prev, WsAsmInsRec::type, WS_ASM_P_LABEL, ws_info(), WsAsmIns, WsBool, and WsCompilerPtr. Referenced by ws_asm_optimize(). 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 /* Nop. */
00143 continue;
00144
00145 /* Remove the jump instruction `i'. */
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 /* Continue from the label `j'. */
00161 i = j;
00162 }
00163
00164 return change;
00165 }
|
Here is the call graph for this function:

|
|
Definition at line 210 of file wsopt.c. References WsCompilerRec::asm_head, WsCompilerRec::asm_tail, WsAsmInsRec::line, WsAsmInsRec::next, WsAsmInsRec::prev, WsAsmInsRec::type, WS_ASM_CONST_0, WS_ASM_CONST_1, WS_ASM_CONST_ES, WS_ASM_CONST_INVALID, WS_ASM_CONST_M1, WS_ASM_CONST_TRUE, ws_asm_ins(), WS_ASM_P_LOAD_CONST, WS_ASM_P_LOAD_VAR, WS_ASM_POP, WS_ASM_RETURN, WS_ASM_RETURN_ES, ws_info(), WsAsmIns, WsBool, and WsCompilerPtr. Referenced by ws_asm_optimize(). 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 /* Two instructions wide peephole. */
00222 if (i->next) {
00223 i2 = i->next;
00224
00225 /*
00226 * {load*,const*} => -
00227 * pop
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 /* Remove both instructions. */
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 * const_es => return_es
00258 * return
00259 */
00260 if (i2->type == WS_ASM_RETURN && i->type == WS_ASM_CONST_ES) {
00261 /* Replace with WS_ASM_RETURN_ES */
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 /* Move forward. */
00286 prev = i;
00287 i = i->next;
00288 }
00289
00290 /* The interpreter will by default return the empty string if a
00291 * function ends without a return statement, so returning the
00292 * empty string at the end of a function is never useful. */
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 }
|
Here is the call graph for this function:

|
|
Definition at line 362 of file wsopt.c. References WsCompilerParamsRec::no_opt_conv, WsCompilerParamsRec::no_opt_dead_code, WsCompilerParamsRec::no_opt_jumps_to_jumps, WsCompilerParamsRec::no_opt_jumps_to_next_instruction, WsCompilerParamsRec::no_opt_peephole, opt_conv(), opt_dead_code(), opt_jumps_to_jumps(), opt_jumps_to_next_instruction(), opt_peephole(), WsCompilerRec::params, WsBool, and WsCompilerPtr. Referenced by compile_stream(). 00363 {
00364 WsBool change = WS_TRUE;
00365
00366 /* While we manage to change the assembler, perform the requested
00367 optimizations. */
00368 while (change) {
00369 change = WS_FALSE;
00370
00371 /* Useless conversions */
00372 if (!compiler->params.no_opt_conv && opt_conv(compiler))
00373 change = WS_TRUE;
00374
00375 /* Peephole. */
00376 if (!compiler->params.no_opt_peephole && opt_peephole(compiler))
00377 change = WS_TRUE;
00378
00379 /* Jumps to jump instructions. */
00380 if (!compiler->params.no_opt_jumps_to_jumps
00381 && opt_jumps_to_jumps(compiler))
00382 change = WS_TRUE;
00383
00384 /* Jumps to the next instruction. */
00385 if (!compiler->params.no_opt_jumps_to_next_instruction
00386 && opt_jumps_to_next_instruction(compiler))
00387 change = WS_TRUE;
00388
00389 /* Unreachable code. */
00390 if (!compiler->params.no_opt_dead_code && opt_dead_code(compiler))
00391 change = WS_TRUE;
00392 }
00393 }
|
Here is the call graph for this function:
