Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

wsopt.c File Reference

#include "wsint.h"
#include "wsasm.h"

Include dependency graph for wsopt.c:

Include dependency graph

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)


Function Documentation

WsBool opt_conv WsCompilerPtr  compiler  )  [static]
 

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:

WsBool opt_dead_code WsCompilerPtr  compiler  )  [static]
 

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:

WsBool opt_jumps_to_jumps WsCompilerPtr  compiler  )  [static]
 

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:

WsBool opt_jumps_to_next_instruction WsCompilerPtr  compiler  )  [static]
 

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:

WsBool opt_peephole WsCompilerPtr  compiler  )  [static]
 

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:

void ws_asm_optimize WsCompilerPtr  compiler  ) 
 

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:

See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.