C:/Users/Dennis/src/lang/russell.orig/src/pass5d/var_in_reg.c

Go to the documentation of this file.
00001 # include <stdio.h>
00002 # include "../parm.h"
00003 # include "op_codes.h"
00004 # include "codegen.h"
00005 # include "datatypes/consnodes.h"
00006 
00007 /* Routines to deal with adjustment of in-line code for the case in     */
00008 /* which the contents of a variable argument are in a virtual register, */
00009 /* and we thus need to uniformly delete one level of indirection in     */
00010 /* accessing that argument.                                             */
00011 
00012 static ConsNode * equiv_regs;
00013                         /* List of registers holding the value of the */
00014                         /* argument we are currently dealing with.    */
00015 
00016 /* Check whether a virtual register is on the above list */
00017 static boolean is_this_arg(reg)
00018 unsigned reg;
00019 {
00020     register ConsNode * p;
00021     
00022     {
00023         for (p = equiv_regs; p != NIL; p = cn_tail(p)) {
00024             if ((unsigned)(cn_head(p)) == reg) {
00025                 return(TRUE);
00026             }
00027         }
00028         return(FALSE);
00029     }
00030 }
00031 
00032 void clear_equiv_regs()
00033 {
00034     register ConsNode *p;
00035 
00036     p = equiv_regs;
00037     while (p != NIL) {
00038         p = cn_del_hd(p);
00039     }
00040     equiv_regs = NIL;
00041 }
00042 
00043 /* Do some flow independent analysis to compute equiv_regs, the set of  */
00044 /* v. registers that can possibly contain copies of the nth argument.   */
00045 /* Code is a complete in-line expansion of a function.                  */
00046 /* returns FALSE iff the argument can be moved to an externally visible */
00047 /* register, e.g. RS                                                    */
00048 
00049 boolean find_equiv_regs(code, n)
00050 struct RIC_instr * code;
00051 int n;
00052 {
00053     register struct RIC_instr *p;
00054     register int i;
00055     unsigned this_arg = n | ARG_BIT;
00056     boolean equiv_regs_changed;
00057 
00058     equiv_regs = cn_cons(this_arg, NIL);
00059     do {
00060         equiv_regs_changed = FALSE;
00061         for (p = code; p != RIC_nil; p = p -> next_instr) {
00062             if (p -> op_code == MOV) {
00063                 if (is_this_arg(p -> arg[0]) && p -> arg[1] != SK) {
00064 #                   ifdef DEBUG
00065                         if ((p -> arg[1]) & ARG_BIT) {
00066                             dbgmsg("only_indirect_ref: clobbered argument\n");
00067                         }
00068 #                   endif
00069                     if (p -> arg[1] == RS
00070                         || p -> arg[1] < FIRST_AVAIL_LOC
00071                            && p -> arg[1] != T1
00072                            && p -> arg[1] != T2) {
00073                         /* arg was moved to externally visible location */
00074                         return(FALSE);
00075                     }
00076                     if (!is_this_arg(p -> arg[1])) {
00077                         equiv_regs_changed = TRUE;
00078                         equiv_regs = cn_cons(p -> arg[1], equiv_regs);
00079                     }
00080                 }
00081             }
00082         }
00083     } while (equiv_regs_changed);
00084     return(TRUE);
00085 }
00086 
00087 
00088 /* Determine whether only the contents of the nth argument, rather than */
00089 /* the nth argument itself, is accessed by code.                        */
00090 
00091 boolean only_indirect_ref(code, n)
00092 struct RIC_instr * code;
00093 int n;
00094 {
00095     register struct RIC_instr *p;
00096 
00097     if (!find_equiv_regs(code, n)) {
00098         return(FALSE);
00099     }
00100     for (p = code; p != RIC_nil; p = p -> next_instr) {
00101         if (!p -> label_arg) {
00102             switch(p -> op_code) {
00103                 case LDI:
00104                 case STI:
00105                     if (is_this_arg(p -> arg[2])
00106                         || is_this_arg(p -> arg[0]) && p -> arg[1] != 0) {
00107                         return(FALSE);
00108                     }
00109                     break;
00110                 case MOV:
00111                     if (!is_this_arg(p -> arg[0])
00112                         && is_this_arg(p -> arg[1])) {
00113                         /* Don't know for sure what's in the register */
00114                         return(FALSE);
00115                     }
00116                     break;
00117                 case LDN:
00118                     if (is_this_arg(p -> arg[1])) {
00119                         return(FALSE);
00120                     }
00121                 case DCL:
00122                 case UDC:
00123                     break;
00124                 default:
00125                     if (is_this_arg(p -> arg[0])
00126                         || is_this_arg(p -> arg[1])
00127                         || is_this_arg(p -> arg[2])) {
00128                         return(FALSE);
00129                     }
00130             }
00131         }
00132     }
00133     clear_equiv_regs();
00134     return(TRUE);
00135 }
00136 
00137 
00138 /* Return a copy of code, modified to adjust for the fact the nth argument */
00139 /* is a variable, whose contents are in register m.                        */
00140 /* All LDI and STI instructions referencing the argument are replaced by   */
00141 /* MOVs.  MOVs of the argument are deleted.  The resulting code should     */
00142 /* contain no remaining references to the nth argument, except             */
00143 /* possibly in a UDC instruction.                                          */
00144 /* This assumes that only_indirect_refs(code,n) is known to TRUE.          */
00145 
00146 struct RIC_instr * unindirect(code, n, m)
00147 struct RIC_instr * code;
00148 int n;
00149 long m;
00150 {
00151     register struct RIC_instr *p;
00152     register struct RIC_instr **ptr_p;  /* Location of pointer to node p */
00153     struct RIC_instr *result;  /* Location of pointer to node p */
00154     unsigned this_arg = n | ARG_BIT;
00155 
00156     if (!find_equiv_regs(code, n)) {
00157         dbgmsg("Unindirect: code argument inappropriate\n");
00158     }
00159     result = copy_RIC(code);
00160     for (p = result, ptr_p = &result; p != RIC_nil;
00161          ptr_p = &(p -> next_instr), p = p -> next_instr) {
00162         if (!p -> label_arg) {
00163 #           ifdef TRACE
00164                extern char * op_code_table[];
00165                printf("%s %d %d %d\n", op_code_table[p -> op_code],
00166                        p -> arg[0], p -> arg[1], p -> arg[2]);
00167 #           endif
00168             switch(p -> op_code) {
00169                 case LDI:
00170                     if (is_this_arg(p -> arg[0])) {
00171                       /* Second argument is known to be 0. */
00172                       /* Replace with MOV.                 */
00173                         p -> op_code = MOV;
00174                         p -> arg[0] = m;
00175                         p -> arg[1] = p -> arg[2];
00176                         p -> arg[2] = SK;
00177                         p -> n_args = 2;
00178                     }
00179                     break;
00180                 case STI:
00181                     if (is_this_arg(p -> arg[0])) {
00182                       /* Second argument is known to be 0. */
00183                       /* Replace with MOV.                 */
00184                         p -> op_code = MOV;
00185                         p -> arg[0] = p -> arg[2];
00186                         p -> arg[1] = m;
00187                         p -> arg[2] = SK;
00188                         p -> n_args = 2;
00189                     }
00190                     break;
00191                 case MOV:
00192                     if (is_this_arg(p -> arg[0])) {
00193                         /* Delete this instruction.  This is safe, since */
00194                         /* we effectively perform copy propagation.      */
00195                         *ptr_p = p -> next_instr;
00196                         /* Should deallocate p here, but we still need */
00197                         /* next_instr pointer ...                      */
00198                     }
00199                     break;
00200                 /* argument can't appear in any other instructions */
00201             }
00202         }
00203     }
00204     clear_equiv_regs();
00205     return(result);
00206 }
00207 
00208 

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