home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 6 / FreshFish_September1994.bin / new / dev / c / hce / hcesource / top / source / reg.c < prev    next >
C/C++ Source or Header  |  1992-09-02  |  18KB  |  852 lines

  1. /* Copyright (c) 1989,1991 by Sozobon, Limited.  Author: Tony Andrews
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  */
  11.  
  12. /*
  13.  * The code in this file deals with "registerizing" local variables and
  14.  * parameters. The general idea is to look for highly referenced local
  15.  * variables and parameters and effectively turn them into register
  16.  * variables automatically. Only the D registers are used, currently, so
  17.  * for pointer variables, a manual "register" declaration in the source
  18.  * code is actually better.
  19.  *
  20.  * We need to be certain of several things about a variable before placing
  21.  * it in a register. It's address must not be taken, and it must not be
  22.  * referred to through "aliases" (e.g. when casting to a shorter object).
  23.  * It must be able to fit in a register. And to keep things like printf from
  24.  * breaking, parameters can only be registerized if none of the parameters
  25.  * have their address taken.
  26.  *
  27.  * The compiler makes this all possible by placing "hints" within the
  28.  * generated assembly code. These hints appear as comments, but are parsed
  29.  * by the optimizer, and the information is stashed away by calling addvar().
  30.  * The hints give us the size and offset of each parameter and local variable.
  31.  * Their names are also given, although that information isn't needed here.
  32.  *
  33.  * There are tradeoffs to be wary of when registerizing. If no register
  34.  * variables exist yet, then "movem" instructions have to be added, requiring
  35.  * more references to make this worthwhile. In the case of parameters, the
  36.  * register has to be initialized from the stack. The four cases are:
  37.  *
  38.  *    Locals    w/ other regs:    1 reference  required
  39.  *        no other regs:    4 references required
  40.  *    Parms    w/ other regs:    2 references required
  41.  *        no other regs:    6 references required
  42.  *
  43.  * The numbers above represent the break-even point based on a savings of
  44.  * 2 bytes per reference, and the incremental cost of adding "movem" or
  45.  * "move" instructions as needed.
  46.  *
  47.  * This optimizes for space only. To optimize for time, each reference would
  48.  * be weighted based on the loop nesting level at which it occurs.
  49.  *
  50.  * Modified by Detlef Wuerkner for AMIGA
  51.  * Changes marked with TETISOFT
  52.  */
  53.  
  54. #include "top.h"
  55.  
  56. #define    MAXLOCALS    100
  57.  
  58. static    struct    linfo {
  59.     long    offset;        /* offset from A6 */
  60.     int    size;        /* size of the object */
  61.     int    ref;        /* # of references to the local */
  62.     int    reg;        /* reg. we assigned it to */
  63.     int    flags;        /* length, etc. */
  64. } locals[MAXLOCALS];
  65.  
  66. #define    ALIASED        0x1    /* offset is aliased with another */
  67. #define    ADDR_TAKEN    0x2    /* address of the variable was taken */
  68.  
  69. #define    IS_LOCAL(x)    (locals[(x)].offset < 0)
  70. #define    IS_PARM(x)    (locals[(x)].offset > 0)
  71.  
  72. static    bool    paddr;        /* address of a parameter was taken */
  73. static    int    lcnt;        /* number of local variables we've seen */
  74. static    int    rcnt;        /* number of locals that got registerized */
  75.  
  76. static    int    omask, nmask;    /* old and new register masks */
  77.  
  78. /*
  79.  * addvar(size, off) - add a variable entry for the current function
  80.  *
  81.  * These come from hints the compiler gives us about local variables.
  82.  * We use the size and offset here to make sure we don't have aliasing
  83.  * problems with the local variables we want to registerize.
  84.  */
  85. void
  86. addvar(size, off)
  87. int    size;
  88. int    off;
  89. {
  90.     locals[lcnt].offset = off;
  91.     locals[lcnt].size = size;
  92.     locals[lcnt].flags = 0;
  93.     locals[lcnt].ref = 0;
  94.  
  95.     lcnt++;
  96. }
  97.  
  98. /*
  99.  * clrvar() - clear the variable list
  100.  */
  101. void
  102. clrvar()
  103. {
  104.     register int    i;
  105.  
  106.     /*
  107.      * re-initialize the local information
  108.      */
  109.     for (i=0; i < MAXLOCALS ;i++) {
  110.         locals[i].ref = 0;
  111.         locals[i].reg = -1;
  112.         locals[i].flags = 0;
  113.         locals[i].offset = 0;
  114.         locals[i].size = 0;
  115.     }
  116.     paddr = FALSE;
  117.     rcnt = lcnt = 0;
  118. }
  119.  
  120. /*
  121.  * setreg() - try to "registerize" local variables in the given function
  122.  */
  123. void
  124. setreg(bp)
  125. BLOCK    *bp;
  126. {
  127.     void    lcheck(), lassign(), lrewrite();
  128.  
  129.     lcheck(bp);
  130.     lassign();
  131.  
  132. #ifdef    DEBUG
  133.     if (debug)
  134.         dump_table();
  135. #endif
  136.  
  137.     if (rcnt > 0)
  138.         lrewrite(bp);
  139.  
  140.     s_reg += rcnt;        /* keep totals for accounting */
  141. }
  142.  
  143. /*
  144.  * lcheck() - scan for local variable references in the given function
  145.  */
  146. static void
  147. lcheck(bp)
  148. BLOCK    *bp;
  149. {
  150.     void    ckref();
  151.     register int    i;
  152.     register BLOCK    *cb;
  153.     register INST    *ci;
  154.  
  155.     for (cb = bp; cb != NULL ;cb = cb->next) {
  156.         for (ci = cb->first; ci != NULL ;ci = ci->next) {
  157.             ckref(ci, &ci->src);
  158.             ckref(ci, &ci->dst);
  159.         }
  160.     }
  161.  
  162.     /*
  163.      * Now figure out which registers are currently used.
  164.      */
  165.     ci = bp->first->next;
  166.  
  167.     if (ci != NULL && ci->opcode == MOVEM) {
  168.         if (ci->src.amode == REG)
  169.             omask = RM(ci->src.areg);
  170.         else
  171.             omask = stomask(ci->src.astr);
  172.     } else
  173.         omask = 0;
  174. }
  175.  
  176. /*
  177.  * ckref() - check for a local variable reference
  178.  *
  179.  * If a local variable reference is found, it's added to the table or
  180.  * (if already there) its reference count is incremented. If we're
  181.  * taking its address, note that too.
  182.  */
  183. static void
  184. ckref(ip, op)
  185. INST    *ip;
  186. struct    opnd    *op;
  187. {
  188.     register int    i;
  189.     register int    sz;
  190.  
  191. /* CHANGED BY TETISOFT (see inst.h) */
  192. /*    if (op->amode != REGID || op->areg != A6) */
  193.     if (op->amode != REGID || op->areg != FRAMEP)
  194.  
  195.         return;
  196.  
  197.     switch (ip->flags) {
  198.     case LENL:
  199.         sz = 4;
  200.         break;
  201.     case LENW:
  202.         sz = 2;
  203.         break;
  204.     case LENB:
  205.     default:        /* for LEA and PEA */
  206.         sz = 1;
  207.         break;
  208.     }
  209.  
  210.     /*
  211.      * is the local variable already in the table?
  212.      */
  213.     for (i=0; i < lcnt ;i++) {
  214.         if (locals[i].offset == op->disp && locals[i].size == sz) {
  215.             locals[i].ref++;
  216.             break;
  217.         }
  218.     }
  219.  
  220.     /*
  221.      * If not in the table, add an entry for it. If we add an entry
  222.      * here, it must be an alias for one of the entries we got via
  223.      * the compiler hints.
  224.      */
  225.     if (i == lcnt) {
  226.         locals[lcnt].offset = op->disp;
  227.         locals[lcnt].size = sz;
  228.         locals[lcnt].flags = 0;
  229.         locals[lcnt].ref = 1;
  230.  
  231.         lcnt++;
  232.     }
  233.  
  234.     if (ip->opcode == LEA || ip->opcode == PEA) {
  235.         locals[i].flags = ADDR_TAKEN;
  236.         /*
  237.          * If we took the address of a parameter, note that
  238.          * by setting 'paddr'.
  239.          */
  240.         if (IS_PARM(i))
  241.             paddr = TRUE;
  242.     }
  243. }
  244.  
  245. /*
  246.  * lassign() - assign local variable to registers
  247.  *
  248.  * Check for aliases, sort the table, and then decide how to assign
  249.  * the local variables to registers.
  250.  */
  251. static void
  252. lassign()
  253. {
  254.     void    ck_aliases(), sort_table(), do_sort();
  255.     register int    i;
  256.     register int    r;
  257.     int    minlref;    /* min. required references for a local */
  258.     int    minpref;    /* min. required references for a parameter */
  259.  
  260.     ck_aliases();        /* disqualify any "aliased" references */
  261.     sort_table();        /* and sort by reference count */
  262.  
  263.     /*
  264.      * If there were already "movem" instructions, then we should
  265.      * convert as many locals as possible to registers. If we're
  266.      * going to have to add the movem's, then we need at least 4
  267.      * references for this to be worthwhile. The 2 movem instructions
  268.      * take 8 bytes, and each reference conversion saves 2 bytes.
  269.      * This analysis optimizes for size.
  270.      */
  271.     minlref = (omask != 0) ? 1 : 4;
  272.     minpref = (omask != 0) ? 2 : 6;
  273.  
  274.     nmask = omask;
  275.  
  276. /* CHANGED BY TETISOFT (see inst.h) */
  277. /*    for (i=0, r=D3; r <= D7 ;) { */
  278.     for (i=0, r=DRV_START; r <= D7 ;) {
  279.  
  280.         /*
  281.          * If the register is already in use, skip it.
  282.          */
  283.         if (omask & RM(r)) {
  284.             r++;
  285.             continue;
  286.         }
  287.  
  288.         /*
  289.          * If no more eligible variables, then stop.
  290.          */
  291.         if (locals[i].ref <= 0)
  292.             break;
  293.  
  294.         /*
  295.          * If something meets the minimums, then assign it to
  296.          * the current register, and adjust the minimums.
  297.          */
  298.         if ((IS_LOCAL(i) && locals[i].ref >= minlref) ||
  299.             (IS_PARM(i)  && locals[i].ref >= minpref)) {
  300.             locals[i].reg = r;
  301.             nmask |= RM(r);
  302.             minlref = 1;
  303.             minpref = 2;
  304.             r++;
  305.             i++;
  306.         } else {
  307.             /*
  308.              * If we run into something that isn't referenced
  309.              * enough, disqualify it and re-sort. There might
  310.              * still be something else worth doing.
  311.              */
  312.             locals[i].ref = -locals[i].ref;
  313.             do_sort();
  314.         }
  315.     }
  316.     rcnt = i;
  317. }
  318.  
  319. /*
  320.  * ck_aliases() - check for aliases in the locals table
  321.  *
  322.  * An alias occurs when two differ