C:/Users/Dennis/src/lang/russell.orig/src/RICfilter/filter.c

Go to the documentation of this file.
00001 # define DEBUG
00002 
00003 # define TRACE
00004 # undef TRACE
00005 # include <stdio.h>
00006 # include "../pass5d/op_codes.h"
00007 # include "../parm.h"
00008 # include "RIC.h"
00009 
00010 # define HASHT_SIZE 32
00011 
00012 # define mod_sz(n)  ((n) & 0x1f)
00013 
00014 typedef struct RIC_instr * RICp;
00015 
00016 # define NO_REG -2
00017 
00018 char label_buf[MAXLABELSZ+1];
00019 
00020 struct RIC_instr * cbb = RIC_nil; /* A List of instructions representing the */
00021                                   /* current basic block.                    */
00022 struct RIC_instr * cbb_last = RIC_nil;
00023                                   /* Pointer to the end of the above list */
00024 
00025 /* Add the instruction p to cbb, following q, or at the */
00026 /* beginning if q = RIC_nil                             */
00027 void add_after(p, q)
00028 RICp p, q;
00029 {
00030     if (q == RIC_nil) {
00031         p -> next_instr = cbb;
00032         /* p -> prev_instr = RIC_nil; */
00033         cbb = p;
00034     } else {
00035         p -> next_instr = q -> next_instr;
00036         p -> prev_instr = q;
00037         q -> next_instr = p;
00038     }
00039     if (p -> next_instr == RIC_nil) {
00040         cbb_last = p;
00041     } else {
00042         p -> next_instr -> prev_instr = p;
00043     }
00044 }
00045 
00046 /* Delete the instruction p from cbb.  Also delete preceding HINT */
00047 /* LBR and LBA instructions that refer to p.                      */
00048 void delete(p)
00049 register RICp p;
00050 {
00051     register RICp prev = p -> prev_instr;
00052     long hint_arg;
00053 
00054     /* Delete instructions modifying p */
00055       while (prev != RIC_nil 
00056            && (prev -> op_code == LBR
00057                || prev -> op_code == LBA
00058                || prev -> op_code == HINT
00059                   && ((hint_arg = prev -> arg[0]) == NP
00060                       || hint_arg == AL
00061                       || hint_arg == NSC
00062                       || hint_arg == STSZ
00063                       || hint_arg == PT))) {
00064         delete(prev);
00065         prev = p -> prev_instr;
00066       }
00067     if (prev == RIC_nil) {
00068         cbb = p -> next_instr;
00069     } else {
00070         p -> prev_instr -> next_instr = p -> next_instr;
00071     }
00072     if (p -> next_instr == RIC_nil) {
00073         cbb_last = p -> prev_instr;
00074     } else {
00075         p -> next_instr -> prev_instr = p -> prev_instr;
00076     }
00077     /* We don't free the node, since that would complicate traversals */
00078 }
00079 
00080 /* Deallocate and clear the current basic block */
00081 void clear_block()
00082 {
00083     register RICp last, next;
00084 
00085     last = cbb;
00086     while (last != RIC_nil) {
00087         next = last -> next_instr;
00088         GC_free(last);
00089         last = next;
00090     }
00091     cbb = RIC_nil;
00092     cbb_last = RIC_nil;
00093 }
00094 
00095 /* Write out the current basic block onto stdout */
00096 void write_block()
00097 {
00098     register RICp p;
00099     register int opc;
00100     register char * s;
00101 
00102     p = cbb;
00103     while (p != RIC_nil) {
00104         opc = p -> op_code;
00105         putw(opc, stdout);
00106         if (p -> label_arg) {
00107             for (s = p -> label; *s != '\0'; s++) {
00108                 putchar(*s);
00109             }
00110             putchar('\0');
00111         } else {
00112             putw(p -> arg[0], stdout);
00113             putw(p -> arg[1], stdout);
00114             putw(p -> arg[2], stdout);
00115         }
00116         p = p -> next_instr;
00117     }
00118 }
00119 
00120 /* Build a three address instruction */
00121 RICp make_instr(opc, arg1, arg2, arg3)
00122 int opc, arg1, arg2, arg3;
00123 {
00124     RICp result = (RICp) GC_malloc(sizeof (struct RIC_instr));
00125 
00126     result -> op_code = opc;
00127     result -> label_arg = FALSE;
00128     result -> arg[0] = arg1;
00129     result -> arg[1] = arg2;
00130     result -> arg[2] = arg3;
00131     /* result -> next_instr = result -> prev_instr = RIC_nil; */
00132     /* result -> second_decl = FALSE; */
00133     return(result);
00134 }
00135 
00136 /* Build an instruction containing a label */
00137 RICp make_lbl_instr(opc, lbl)
00138 int opc;
00139 char * lbl;
00140 {
00141     int len = strlen(lbl);
00142     RICp result = (RICp) GC_malloc(sizeof (struct RIC_instr) + len);
00143 
00144     result -> op_code = opc;
00145     result -> label_arg = TRUE;
00146     strcpy(result -> label, lbl);
00147     /* result -> next_instr = result -> prev_instr = RIC_nil; */
00148     return(result);
00149 }
00150 
00151 /* Read an instruction from stdin.  Return a pointer to */
00152 /* the instruction.                                     */
00153 RICp read_instr()
00154 {
00155     int opc;
00156     int i;
00157     int arg;
00158 
00159     opc = getw(stdin);
00160     if (feof(stdin)) {
00161         return(RIC_nil);
00162     }
00163     if (opc >= N_OP_CODES) {
00164         fprintf(stderr, "RICfilter: bad op code\n");
00165         exit(1);
00166     }
00167     if (opc <= MAX_LABEL_OP) {
00168         char *p = label_buf;
00169         int c;
00170         int i = 0;
00171             
00172         while ((c = getchar()) != '\0' && c != EOF) {
00173             *p++ = c;
00174             if (++i >= MAXLABELSZ) {
00175                 fprintf(stderr, "Label too long\n");
00176                 p = label_buf;
00177             }
00178         }
00179         *p = '\0';
00180         return(make_lbl_instr(opc, label_buf));
00181     } else {
00182         int arg1, arg2, arg3;
00183 
00184         arg1 = getw(stdin);
00185         arg2 = getw(stdin);
00186         arg3 = getw(stdin);
00187         if (opc == HINT && arg1 == OPT) {
00188             int cnt = arg2;
00189 
00190             /* Discard cnt instructions */
00191                 for (; cnt > 0; cnt --) {
00192                     GC_free(read_instr());
00193                 }
00194             return(read_instr());
00195         } else {
00196             return(make_instr(opc, arg1, arg2, arg3));
00197         }
00198     }
00199 }
00200 
00201 
00202 # define is_real_reg(r) ((r) >= FIRST_AVAIL_LOC || (r) == TL \
00203                          || (r) == RL || (r) == T2)
00204 
00205 /* Set the result_reg, arg_reg, and side_effect fields   */
00206 /* of instruction p.  Among special registers, only RL,  */
00207 /* TL, and T2 are considered to be "real registers".     */
00208 void set_regs(p)
00209 RICp p;
00210 {
00211     register int result = NO_REG;
00212     register int op1 = NONE;
00213     register int op2 = NONE;
00214     int op1r, op2r;
00215     register boolean has_se = FALSE;    /* Instruction has a side effect */
00216 
00217     switch(p -> op_code) {
00218         case BR:
00219         case BRT:
00220         case BRF:
00221         case LBL:
00222         case EXT:
00223         case LBA:
00224         case BFN:
00225         case TFB:
00226         case TFE:
00227         case PRO:
00228         case ADT:
00229         case ERR:
00230         case BSF:
00231         case DCL:
00232         case UDC:
00233         case RTN:
00234         case IDT:
00235         case DDT:
00236         case FDT:
00237         case LBR:
00238             has_se = TRUE;
00239             break;
00240         case STI:
00241             op1 = 0;
00242             op2 = 2;
00243             has_se = TRUE;
00244             break;
00245         case TAR: 
00246             op1 = 0;
00247             op2 = 1;
00248             has_se = TRUE;
00249             break;
00250         case HINT:
00251             switch(p -> arg[0]) {
00252                 case DEA:
00253                 case STSZ:
00254                 case DEAD:
00255                 case LIVE:
00256                     op1 = 1;
00257                     break;
00258             }
00259             has_se = TRUE;
00260             break;
00261         case ARG:
00262             op1 = 1;
00263             has_se = TRUE;
00264             break;
00265         case ALS:
00266         case PSH:
00267             op1 = 0;
00268             has_se = TRUE;
00269             break;
00270         case CLL:
00271         case CLC:
00272             has_se = TRUE;
00273             result = RL;
00274             break;
00275         case CLI:
00276             has_se = TRUE;
00277             op1 = 0;
00278             result = RL;
00279             break;
00280         case LDL:
00281         case TRU:
00282         case FLS:
00283         case LDS:
00284             result = p -> arg[0];
00285             break;
00286         case ALH:
00287         case ALA:
00288             has_se = TRUE;
00289             op1 = 0;
00290         case GAR:
00291         case LDN:
00292             result = p -> arg[1];
00293             break;
00294         case MOV:
00295         case NGI:
00296         case ABI:
00297         case NOT:
00298         case NGF:
00299         case EXF:
00300             op1 = 0;
00301             result = p -> arg[1];
00302             break;
00303         case LDI:
00304         case LDC:
00305             op1 = 0;
00306             result = p -> arg[2];  
00307             break;   
00308         case ADI:
00309         case SBI:
00310         case MLI:
00311         case DVI:
00312         case EQI:
00313         case LTI:
00314         case GTI:
00315         case NEI:
00316         case LEI:
00317         case GEI:
00318         case SHI:
00319         case AND:
00320         case OR:
00321         case ADP:
00322         case ADF:
00323         case SBF:
00324         case MLF:
00325         case DVF:
00326         case EQF:
00327         case LTF:
00328         case GTF:
00329         case NEF:
00330         case LEF:
00331         case GEF:
00332         case SHF:
00333             op1 = 0;
00334             op2 = 1;
00335             result = p -> arg[2];  
00336             break;   
00337         default:
00338             fprintf(stderr, "RICfilter: strange opcode: %d\n", p -> op_code);
00339             abort();
00340             break;
00341     }
00342 #   ifdef DEBUG
00343         if (result == NO_REG && !has_se) {
00344             fprintf(stderr, "RICfilter: vacuous instruction: %d\n",
00345                     p -> op_code);
00346             abort();
00347         }
00348 #   endif
00349     if (result == SK) {
00350         result = NO_REG;
00351     } else if (result < FIRST_AVAIL_LOC && result != RL &&
00352                result != TL && result != T2) {
00353         result = NO_REG;
00354         has_se = TRUE;
00355     }
00356     op1r = p -> arg[op1];
00357     if (!is_real_reg(op1r)) {
00358         op1 = NONE;
00359     }
00360     op2r = p -> arg[op2];
00361     if (!is_real_reg(op2r)) {
00362         op2 = NONE;
00363     }
00364     p -> op1_reg = op1;
00365     p -> op2_reg = op2;
00366     p -> result_reg = result;
00367     p -> side_effect = has_se;
00368 }
00369 
00370 /* The hash table structure used to keep track of info associated with regs */
00371 /* as we are making a pass over the code.                                   */
00372 struct reg_descr {
00373     struct reg_descr * next_reg;
00374     struct reg_descr * next_mapped_reg;  /* Link for mapped regs list */
00375     int this_reg;
00376     int status;
00377 #       define S_LIVE 0
00378 #       define S_DEAD 1 /* known to be dead at this point */
00379 #       define S_UDC  2 /* Only subsequent use us in UDC  */
00380     int equiv_reg;  /* Register to be used instead of this one.    */
00381                     /* Guaranteed to have the same contents as     */
00382                     /* this one.                                   */
00383                     /* Note that equiv_reg will never itself be    */
00384                     /* forwarded to another one.                   */
00385     struct reg_descr * mapped_regs;
00386                     /* Descriptors of registers mapped to this one via */
00387                     /* equiv_regs field.                               */
00388     long const_val;  /* Constant value contained in this register */
00389 #       define NOT_CONSTANT 0x40000000
00390 };
00391 
00392 typedef struct reg_descr * regp;
00393 
00394 # define reg_nil ((regp) 0)
00395 
00396 regp hasht[HASHT_SIZE];
00397 
00398 regp lookup();
00399 
00400 /* Invalidate register equivalences and constant information involving r */
00401 void clear_equiv(r)
00402 regp r;
00403 {
00404     regp p, q, s;
00405     regp * t_ptr;
00406     int equiv;
00407 #   ifdef DEBUG
00408         boolean foundit = FALSE;
00409 #   endif
00410 
00411 #   ifdef TRACE
00412         fprintf(stderr, "Clear_equiv: %d\n", r -> this_reg);
00413 #   endif
00414     /* Clear mappings of other registers to this one. */
00415       for (p = r -> mapped_regs; p != reg_nil; p = q) {
00416 #   ifdef TRACE
00417         fprintf(stderr, "\tClearing mapping from %d\n", p -> this_reg);
00418 #   endif
00419         q = p -> next_mapped_reg;
00420 #       ifdef DEBUG
00421             if (p -> equiv_reg != r -> this_reg) {
00422                 fprintf(stderr,
00423                         "RICfilter: Register equivalence table messed up\n");
00424                 abort(r,p);
00425             }
00426 #       endif
00427         p -> equiv_reg = NO_REG;
00428         p -> next_mapped_reg = reg_nil;
00429       }
00430     /* Clear mapping info for r */
00431       if ((equiv = r -> equiv_reg) != NO_REG && is_real_reg(equiv)) {
00432         s = lookup(equiv);
00433         /* remove r from s's list of mapped registers */
00434           for (t_ptr = &(s -> mapped_regs); *t_ptr != reg_nil;
00435                t_ptr = &((*t_ptr) -> next_mapped_reg)) {
00436 #           ifdef DEBUG
00437               if ((*t_ptr) -> equiv_reg != r -> equiv_reg) {
00438                 fprintf(stderr, "RICfilter: bad reg on list\n");
00439                 abort(*t_ptr, r);
00440               }
00441 #           endif
00442             /* *t_ptr is the list entry currently being examined */
00443             if (*t_ptr == r) {
00444               *t_ptr = r -> next_mapped_reg;
00445               r -> next_mapped_reg = reg_nil;
00446 #             ifdef DEBUG
00447                 foundit = TRUE;
00448 #             endif
00449               break;
00450             }
00451           }
00452 #       ifdef DEBUG
00453             if (!foundit) {
00454               fprintf(stderr,
00455                       "RICfilter: mapped register not on list\n");
00456               abort(r,s);
00457             }
00458 #       endif
00459       }
00460       r -> equiv_reg = NO_REG;
00461       r -> mapped_regs = reg_nil;
00462       r -> const_val = NOT_CONSTANT;
00463 }
00464 
00465 /* Return the hash table entry corresponding to reg_no */
00466 /* allocate an entry if there previously was none.     */
00467 regp lookup(reg_no)
00468 int reg_no;
00469 {
00470     regp * he = &(hasht[mod_sz(reg_no)]);
00471     regp p;
00472 
00473     for (p = *he; p != reg_nil; p = p -> next_reg) {
00474         if (p -> this_reg == reg_no) {
00475             return(p);
00476         }
00477     }
00478     p = (regp) GC_malloc(sizeof(struct reg_descr));
00479     p -> this_reg = reg_no;
00480     p -> next_reg = *he;
00481     /* p -> status = S_LIVE; */
00482     /* p -> mapped_regs = reg_nil; */
00483     /* p -> next_mapped_reg = reg_nil; */
00484     p -> equiv_reg = NO_REG;
00485     p -> const_val = NOT_CONSTANT;
00486     *he = p;
00487     return(p);
00488 }
00489 
00490 /* Clear the hash table of register descriptions */
00491 /* Flush any UDCs that are still pending         */
00492 void clear_hasht()
00493 {
00494     int i;
00495     regp p, q;
00496 
00497     for (i = 0; i < HASHT_SIZE; i++) {
00498         for (p = hasht[i]; p != reg_nil;) {
00499             q = p -> next_reg;
00500             if (p -> status == S_UDC) {
00501 #               ifdef TRACE
00502                     fprintf(stderr, "Flushing UDC for register %d\n", p -> this_reg);
00503 #               endif
00504                 add_after(make_instr(UDC, p -> this_reg, SK, SK), RIC_nil);
00505             }
00506             GC_free(p);
00507             p = q;
00508         }
00509         hasht[i] = reg_nil;
00510     }
00511 }
00512 
00513 long const_arg_table[3];
00514                     /* Constant values of the first 3 arguments to */
00515                     /* the current function call.  NOT_CONSTANT    */
00516                     /* for a non-constant parameter.               */
00517 RICp arg_instrs[3];
00518                     /* The ARG instructions for the first 3 args */
00519                     /* for the current function call.            */
00520 
00521 /* Perform local copy propogation on the current basic block */
00522 /* Set status to S_UDC for those regs that are undeclared    */
00523 /* before the end of the block.  (This is done here, so that */
00524 /* we can continue to use registers past the original UDC.)  */
00525 /* The status of RL and TL is set to S_UDC if the locations  */
00526 /* where undeclared after the last assignment to them.       */
00527 /* We also maintain const_arg_table and replace calls to the */
00528 /* floating point dot operations by constants when possible. */
00529 void propagate()
00530 {
00531     register RICp p;
00532     register int reg;
00533     register int reg2;
00534     regp q, r;
00535     int i;
00536 
00537     for (p = cbb; p != RIC_nil; p = p -> next_instr) {
00538         switch(p -> op_code) {
00539           case MOV:
00540             reg = p -> arg[1];
00541             if (is_real_reg(reg)) {
00542                 reg2 = p -> arg[0];
00543                 /* Is it already a copy? */
00544                 if (is_real_reg(reg2)) {
00545                     q = lookup(reg2);
00546                     if (q -> equiv_reg != NO_REG) {
00547                         reg2 = q -> equiv_reg;
00548                     }
00549                 }
00550                 q = lookup(reg);
00551                 if (reg == TL || reg == RL) {
00552                     q -> status = S_LIVE;   /* Preceding UDC not valid at */
00553                                             /* end of basic block         */
00554                 }
00555                 if (reg == reg2) {
00556 #                   ifdef TRACE
00557                         fprintf(stderr, "Deleting redundant MOV\n");
00558 #                   endif
00559                     delete(p);
00560                 } else {
00561                     if (q -> equiv_reg != NO_REG
00562                         && is_real_reg(q -> equiv_reg)
00563                         || q -> mapped_regs != reg_nil) {
00564                         clear_equiv(q);
00565                     }
00566                     if (reg2 != SP /* may change unexpectedly */) {
00567                         q -> equiv_reg = reg2;
00568                     }
00569                     if (is_real_reg(reg2)) {
00570                         r = lookup(reg2);
00571                         q -> next_mapped_reg = r -> mapped_regs;
00572                         r -> mapped_regs = q;
00573                         q -> const_val = r -> const_val;
00574                     } else {
00575                         /* Set const_val */
00576                           switch(reg2) {
00577                             case C0:
00578                                 q -> const_val = 0;
00579                                 break;
00580                             case C1:
00581                                 q -> const_val = 1;
00582                                 break;
00583                             case C2:
00584                                 q -> const_val = 2;
00585                                 break;
00586                             case C3:
00587                                 q -> const_val = 3;
00588                                 break;
00589                             case C4:
00590                                 q -> const_val = 4;
00591                                 break;
00592                             default:
00593                                 q -> const_val = NOT_CONSTANT;
00594                                 break;
00595                           }
00596                     }
00597 #                   ifdef TRACE
00598                         fprintf(stderr, "%d is a copy of %d\n", reg, reg2);
00599 #                   endif
00600                 }
00601             }
00602             break;
00603 
00604           case ARG:
00605             q = reg_nil;
00606             reg = p -> arg[1];
00607             if (is_real_reg(reg)) {
00608                 q = lookup(reg);
00609                 if (q -> equiv_reg != NO_REG) {
00610                     /* Replace by an equivalent register */
00611 #                   ifdef TRACE
00612                         fprintf(stderr,
00613                                 "Replacing reference to %d in ARG by one to %d\n",
00614                                 reg, q -> equiv_reg);
00615 #                   endif
00616                     p -> arg[1] = q -> equiv_reg;
00617                 }
00618             }
00619             i = p -> arg[0] - 1;  /* 0-based argument number */
00620             if (i < 3) {
00621               /* Update const_arg_table and arg_instrs */
00622                 arg_instrs[i] = p;
00623                 if (q != reg_nil /* real register */) {
00624                     const_arg_table[i] = q -> const_val;
00625                 } else {
00626                     switch(reg) {
00627                         case C0:
00628                             const_arg_table[i] = 0;
00629                             break;
00630                         case C1:
00631                             const_arg_table[i] = 1;
00632                             break;
00633                         case C2:
00634                             const_arg_table[i] = 2;
00635                             break;
00636                         case C3:
00637                             const_arg_table[i] = 3;
00638                             break;
00639                         case C4:
00640                             const_arg_table[i] = 4;
00641                             break;
00642                         default:
00643                             const_arg_table[i] = NOT_CONSTANT;
00644                     }
00645                 }
00646             }
00647             break;
00648 
00649           case CLC:
00650             {
00651 #               define DP_DOT "_Float_Dot"
00652 #               define SP_DOT "_SFloat_Dot"
00653 #               define SBFSZ 120
00654                 RICp clc_instr = p;
00655                 RICp lba_instr = p -> prev_instr;
00656                 RICp next_i = p -> next_instr; /* Cant be NIL */
00657                 RICp prev_i;
00658                 RICp const_i;
00659                 RICp q;
00660                 char * routine_name = lba_instr -> label;
00661                 boolean args_constant = TRUE;
00662                 boolean is_dp_dot;
00663                 boolean is_sp_dot;
00664                 char buf[SBFSZ];
00665 
00666                 if (clc_instr -> arg[0] == 3) {
00667                     for (i = 0; i < 3; i++) {
00668                         args_constant &= (const_arg_table[i] != NOT_CONSTANT);
00669                     }
00670                     if (const_arg_table[2] > SBFSZ - 30) {
00671                         /* Possibly absurd floating point constant.  */
00672                         /* Dont bother with it.                      */
00673                         args_constant = FALSE;
00674                     }
00675                     if (args_constant) {
00676                       is_dp_dot = (strcmp(routine_name, DP_DOT) == 0);
00677                       is_sp_dot = (strcmp(routine_name, SP_DOT) == 0);
00678                     }
00679                     if (args_constant &&
00680                         (is_dp_dot || is_sp_dot)) {
00681                         /* Delete argument instructions */
00682                           for (i = 0; i < 3; i++) {
00683                             delete(arg_instrs[i]);
00684                           }
00685                         /* Delete the call and LBA */
00686                           delete(clc_instr);
00687                         /* Reconstruct the floating point constant */
00688                           sprintf(buf, "%d.%0*d",
00689                                   const_arg_table[0],
00690                                   const_arg_table[2],
00691                                   const_arg_table[1]);
00692                         /* Insert the floating point constant into the code */
00693                           prev_i = next_i -> prev_instr;
00694                           if (is_dp_dot) {
00695                             const_i = make_lbl_instr(DDT, buf);
00696                           } else {
00697                             const_i = make_lbl_instr(FDT, buf);
00698                           }
00699                           set_regs(const_i);
00700                           add_after(const_i, prev_i);
00701                           q = make_lbl_instr(LBA, "1");
00702                           set_regs(q);
00703                           add_after(q, prev_i);
00704                         /* Load it into RL */
00705                           if (is_sp_dot) {
00706                             q = make_instr(LDI, RL, 0, RL);
00707                             set_regs(q);
00708                             add_after(q, const_i);
00709                           }
00710                           q = make_instr(LDL, RL, SK, SK);
00711                           set_regs(q);
00712                           add_after(q, const_i);
00713                           q = make_lbl_instr(LBA, "1b");
00714                           set_regs(q);
00715                           add_after(q, const_i);
00716                     }
00717                 }
00718                 /* Update register table to reflect the fact that */
00719                 /* RL was clobbered.                              */
00720                   r = lookup(RL);
00721                   clear_equiv(r);
00722                   r -> status = S_LIVE;
00723             }
00724             break;
00725 
00726           case UDC:
00727             if (is_real_reg(p -> arg[0])) {
00728               q = lookup(p -> arg[0]);
00729               q -> status = S_UDC;
00730             }
00731             break;
00732 
00733           case DCL:
00734             q = lookup(p -> arg[0]);
00735             if (q -> status == S_UDC) {
00736                 /* previously declared and undeclared */
00737                 p -> second_decl = TRUE;
00738             }
00739             q -> status = S_LIVE;
00740             break;
00741 
00742           case LDN:
00743             reg = p -> arg[1];
00744             if (reg == SK) {
00745                 delete(p);
00746                 break;
00747             }
00748 #           ifdef DEBUG
00749                 if (!is_real_reg(reg)) {
00750                     fprintf(stderr, "RICfilter: bad LDN arg\n");
00751                     abort();
00752                 }
00753 #           endif
00754             q = lookup(reg);
00755             if (reg == TL || reg == RL) {
00756                 q -> status = S_LIVE;   /* Preceding UDC not valid at */
00757                                         /* end of basic block         */
00758             }
00759             if (q -> mapped_regs != reg_nil) {
00760                 clear_equiv(q);
00761             }
00762             q -> const_val = p -> arg[0];
00763             switch(p -> arg[0]) {
00764                 case 0:
00765                     q -> equiv_reg = C0;
00766                     break;
00767                 case 1:
00768                     q -> equiv_reg = C1;
00769                     break;
00770                 case 2:
00771                     q -> equiv_reg = C2;
00772                     break;
00773                 case 3:
00774                     q -> equiv_reg = C3;
00775                     break;
00776                 case 4:
00777                     q -> equiv_reg = C4;
00778                     break;
00779                 default:
00780                     q -> equiv_reg = NO_REG;
00781                     break;
00782             }
00783             break;
00784 
00785           case ALA:
00786           case ALH:
00787             /* These may clobber RL */
00788             q = lookup(RL);
00789             clear_equiv(q);
00790             /* and continue: */
00791 
00792           default:
00793             reg = p -> result_reg;
00794             if (reg != NO_REG) {
00795                 q = lookup(reg);
00796                 if (q -> equiv_reg != NO_REG || q -> mapped_regs != reg_nil) {
00797                     clear_equiv(q);
00798                 }
00799                 if (reg == TL || reg == RL) {
00800                     q -> status = S_LIVE;   /* Preceding UDC not valid at */
00801                                             /* end of basic block         */
00802                 }
00803             }
00804             if (p -> op1_reg != NONE) {
00805                 reg = p -> arg[p -> op1_reg];
00806                 q = lookup(reg);
00807                 if (q -> equiv_reg != NO_REG) {
00808                     /* Replace by an equivalent register */
00809 #                   ifdef TRACE
00810                         fprintf(stderr,
00811                                 "Replacing reference to %d by one to %d\n",
00812                                 p -> arg[p -> op1_reg], q -> equiv_reg);
00813 #                   endif
00814                     p -> arg[p -> op1_reg] = q -> equiv_reg;
00815                 }
00816             }
00817             if (p -> op2_reg != NONE) {
00818                 reg = p -> arg[p -> op2_reg];
00819                 q = lookup(reg);
00820                 if (q -> equiv_reg != NO_REG) {
00821                     /* Replace by an equivalent register */
00822 #                   ifdef TRACE
00823                         fprintf(stderr,
00824                                 "Replacing reference to %d by one to %d\n",
00825                                 p -> arg[p -> op2_reg], q -> equiv_reg);
00826 #                   endif
00827                     p -> arg[p -> op2_reg] = q -> equiv_reg;
00828                 }
00829             }
00830         }
00831     }
00832 }
00833 
00834 /* Perform dead code elimination and insert hints about dead registers into */
00835 /* the current basic block.                                                 */
00836 void eliminate()
00837 {
00838     RICp p;
00839     regp q;
00840     boolean deleted;
00841 
00842     for (p = cbb_last; p != RIC_nil; p = p -> prev_instr) {
00843 #       ifdef DEBUG
00844             if (p -> result_reg == 0) {
00845                 fprintf(stderr, "RICfilter: Missing result info\n");
00846             }
00847 #       endif
00848         switch (p -> op_code) {
00849             case UDC:
00850                 /* Was already entered as undeclared in register table */
00851                 /* Will be regenerated in a more appropriate place.    */
00852                 delete(p);
00853             break;
00854             case DCL:
00855                 q = lookup(p -> arg[0]);
00856                 if (q -> status == S_UDC) {
00857                     /* Location not used */
00858 #                   ifdef TRACE
00859                       fprintf(stderr, "Deleting DCL %d\n", p -> arg[0]);
00860 #                   endif
00861                     delete(p);
00862                 }
00863                 if (p -> second_decl) {
00864                     q -> status = S_UDC;
00865                     /* Need to generate another UDC */
00866                 } else {
00867                     q -> status = S_DEAD;  /* Don't need to generate UDC */
00868                 }
00869                 break;
00870             default:
00871                 deleted = FALSE;
00872                 if (!(p -> side_effect)) {
00873                     if (p -> result_reg == NO_REG) {
00874 #                       ifdef TRACE
00875                           fprintf(stderr,
00876                                   "deleting result-less instruction, opcode = %d\n",
00877                                   p -> op_code);
00878 #                       endif
00879                         delete(p);
00880                         deleted = TRUE;
00881                     } else {
00882                         q = lookup(p -> result_reg);
00883                         if (q -> status == S_UDC
00884                             || q -> status == S_DEAD) {
00885 #                           ifdef TRACE
00886                               fprintf(stderr,
00887                                       "deleting dead instruction, opcode = %d, result = %d\n",
00888                                       p -> op_code, p -> result_reg);
00889 #                           endif
00890                             delete(p);
00891                             deleted = TRUE;
00892                         }
00893                     }
00894                 }
00895                 if (!deleted) {
00896                     int opr1, opr2;
00897 
00898                     /* update liveness info for result register, */
00899                     /* and reinsert UDC for result, if necessary */
00900                         if (p -> result_reg != NO_REG) {
00901                             q = lookup(p -> result_reg);
00902                             if (q -> status == S_UDC) /* unlikely, but ...*/ {
00903                                 add_after(make_instr(UDC, p -> result_reg,
00904                                                      SK, SK), p);
00905                             } else if (q -> status == S_DEAD) {
00906                                 add_after(make_instr(HINT, DEAD,
00907                                                      p -> result_reg,
00908                                                      SK), p);
00909                             }
00910                             q -> status = S_DEAD;
00911                         }
00912                     /* update liveness info for arguments, and insert UDCs */
00913                         if (p -> op1_reg != NONE) {
00914                             opr1 = p -> arg[p -> op1_reg];
00915                             q = lookup(opr1);
00916                             if (q -> status == S_UDC) {
00917                                 add_after(make_instr(UDC, opr1, SK, SK), p);
00918                             } else if (q -> status == S_DEAD
00919                                        && opr1 != p -> result_reg) {
00920                                 add_after(make_instr(HINT, DEAD, opr1, SK), p);
00921                             }
00922 #                           ifdef TRACE
00923                               fprintf(stderr,
00924                                       "Changing status of %d to S_LIVE\n",
00925                                       opr1);
00926 #                           endif
00927                             q -> status = S_LIVE;
00928                         }
00929                         if (p -> op2_reg != NONE) {
00930                             opr2 = p -> arg[p -> op2_reg];
00931                             q = lookup(opr2);
00932                             if (q -> status == S_UDC) {
00933                                 add_after(make_instr(UDC, opr2, SK, SK), p);
00934                             } else if (q -> status == S_DEAD
00935                                        && opr2 != p -> result_reg) {
00936                                 add_after(make_instr(HINT, DEAD, opr2, SK), p);
00937                             }
00938 #                           ifdef TRACE
00939                               fprintf(stderr,
00940                                       "Changing status of %d to S_LIVE\n",
00941                                       opr2);
00942 #                           endif
00943                             q -> status = S_LIVE;
00944                         }
00945                 }
00946         }
00947     }
00948 }
00949 
00950 /* Perform optimizations on current basic block */
00951 void optimize_block()
00952 {
00953     /* Propagate copies */
00954       propagate();
00955     /* eliminate dead code, propagate back UDCs, and insert HINT DEADs */
00956       eliminate();
00957     /* Deallocate register hash table and flush pending UDCs */
00958       clear_hasht();
00959 }
00960 
00961 main(argc, argv)
00962 int argc;
00963 char ** argv;
00964 {
00965     RICp ci;        /* current instruction */
00966     RICp pi;        /* previous instruction */
00967     int opc;
00968 
00969     GC_init();
00970     if (argc != 1) {
00971         fprintf(stderr, "%s takes no arguments\n", argv[0]);
00972         exit(1);
00973     }
00974     pi = RIC_nil;
00975     while ((ci = read_instr()) != RIC_nil) {
00976         set_regs(ci);
00977         add_after(ci,pi);
00978         pi = ci;
00979         opc = ci -> op_code;
00980         if (opc == BSF || opc == BFN || opc == BRT || opc == BRF
00981             || opc == BR || opc == LBL) {
00982             /* Process one basic block, and set up for the next one */
00983               optimize_block();
00984               write_block();
00985               clear_block();
00986               pi = RIC_nil;
00987         }
00988     }
00989     optimize_block();
00990     write_block();
00991     clear_block();
00992     exit(0);
00993 }

Generated on Fri Jan 25 10:39:48 2008 for russell by  doxygen 1.5.4