cvsuser     03/11/03 16:37:30

  Modified:    imcc     imc.h imc.c parser_util.c
  Log:
  Reorg some code, move some stuff to header file.
  
  Revision  Changes    Path
  1.53      +32 -9     parrot/imcc/imc.h
  
  Index: imc.h
  ===================================================================
  RCS file: /cvs/public/parrot/imcc/imc.h,v
  retrieving revision 1.52
  retrieving revision 1.53
  diff -u -w -r1.52 -r1.53
  --- imc.h     4 Nov 2003 00:03:52 -0000       1.52
  +++ imc.h     4 Nov 2003 00:37:30 -0000       1.53
  @@ -28,6 +28,12 @@
   #define EXTERN extern
   #endif
   
  +#define SPILL_STRESS 0
  +    
  +#if SPILL_STRESS 
  +# undef MAX_COLOR
  +# define MAX_COLOR 4
  +#endif      
   
   #include "symreg.h"
   #include "instructions.h"
  @@ -45,22 +51,43 @@
    */
   #define MAX_COLOR NUM_REGISTERS
   
  +/*
  + * imc.c
  + */
   void imc_compile_unit(struct Parrot_Interp *, Instruction * unit);
   
  -void free_reglist(struct Parrot_Interp *);
   
  +/*
  + * instructions.c
  + */
  +void init_tables(struct Parrot_Interp * interp);
  +
  +/*
  + * optimizer.c
  + */
   const char * get_neg_op(char *op, int *nargs);
   
  +/*
  + * reg_alloc.c
  + */
  +void imc_reg_alloc(struct Parrot_Interp *, Instruction * unit);
  +void free_reglist(struct Parrot_Interp *);
  +
  +/*
  + * parser_util.c
  + */
  +int get_keyvec(Parrot_Interp, int opnum);
   int check_op(struct Parrot_Interp *, char * fullname, char *op, SymReg *r[],
       int narg, int keyvec);
  -int get_keyvec(Parrot_Interp, int opnum);
   int is_op(struct Parrot_Interp *, char *);
  -void init_tables(struct Parrot_Interp * interp);
  -
  +char *str_dup(const char *);
  +char *str_cat(const char *, const char *);
   int imcc_vfprintf(FILE *fd, const char *format, va_list ap);
   int imcc_fprintf(FILE *fd, const char *fmt, ...);
   
  -/* pcc protos */
  +/* 
  + * pcc.c
  + */
   void expand_pcc_sub(Parrot_Interp interpreter, Instruction *ins);
   void expand_pcc_sub_call(Parrot_Interp interpreter, Instruction *ins);
   void expand_pcc_sub_ret(Parrot_Interp interpreter, Instruction *ins);
  @@ -69,10 +96,6 @@
   int pcc_sub_reads(Instruction* ins, SymReg* r);
   int pcc_sub_writes(Instruction* ins, SymReg* r);
   
  -/* This should be common with Cola */
  -
  -char *str_dup(const char *);
  -char *str_cat(const char *, const char *);
   
   /* globals */
   
  
  
  
  1.61      +7 -1039   parrot/imcc/imc.c
  
  Index: imc.c
  ===================================================================
  RCS file: /cvs/public/parrot/imcc/imc.c,v
  retrieving revision 1.60
  retrieving revision 1.61
  diff -u -w -r1.60 -r1.61
  --- imc.c     27 Oct 2003 06:39:20 -0000      1.60
  +++ imc.c     4 Nov 2003 00:37:30 -0000       1.61
  @@ -1,14 +1,9 @@
  -/* Register allocator:
  - *
  - * This is a brute force register allocator. It uses a graph-coloring
  - * algorithm, but the implementation is very kludgy.
  - *
  - * It is a partial implementation of a Briggs-style register allocator
  - * The following parts are just missing:
  +/*
  + * imc.c
    *
  - * - Renumbering
  - * - Coaelesceing
  + * Main entry point and top level of IMCC compiler.
    *
  + * Moved all register allocation and spill code to reg_alloc.c
    */
   
   #include <string.h>
  @@ -16,1045 +11,18 @@
   #include "imc.h"
   #include "optimizer.h"
   
  -/* recalculate CFG and register life for all syms, with this
  - * set to 1, the old and slow routines are used
  - * with 0, this info is recalced on the fly during spilling
  - */
  -#define DOIT_AGAIN_SAM 0
  -
  -#define SPILL_STRESS 0
  -
  -#if SPILL_STRESS
  -# undef MAX_COLOR
  -# define MAX_COLOR 4
  -#endif
  -
  -static void make_stat(int *sets, int *cols);
  -static void imc_stat_init(void);
  -static void print_stat(Parrot_Interp);
  -static void allocate_wanted_regs(void);
  -static void build_reglist(Parrot_Interp, Instruction * unit);
  -static void build_interference_graph(Parrot_Interp);
  -static void compute_du_chain(Instruction * unit);
  -static int interferes(Parrot_Interp, SymReg * r0, SymReg * r1);
  -static int map_colors(int x, SymReg ** graph, int colors[], int typ);
  -#ifdef DO_SIMPLIFY
  -static int simplify (void);
  -#endif
  -static void compute_spilling_costs (Parrot_Interp);
  -static void order_spilling (void);
  -static void spill (struct Parrot_Interp *, Instruction * unit, int);
  -static int try_allocate(Parrot_Interp);
  -static void restore_interference_graph(void);
  -static int neighbours(int node);
  -
  -extern int pasm_file;
  -/* Globals: */
  -
  -static IMCStack nodeStack;
  -static SymReg** interference_graph;
  -static SymReg** reglist;
  -static int n_symbols;
   
  -/* imc_compile_unit is the main loop of the allocation algorithm. It operates
  +/* imc_compile_unit is the main loop of the IMC compiler for each unit. It operates
    * on a single compilation unit at a time.
    */
   void
   imc_compile_unit(struct Parrot_Interp *interpreter, Instruction * unit)
   {
  -    int to_spill;
  -    int todo, first;
  -
  -    if (!unit)
  -        return;
  -    if (!optimizer_level && pasm_file)
  -        return;
  -
  -    init_tables(interpreter);
  -    allocated = 0;
  -
  -    debug(interpreter, DEBUG_IMC, "\n------------------------\n");
  -    debug(interpreter, DEBUG_IMC, "processing sub %s\n", function);
  -    debug(interpreter, DEBUG_IMC, "------------------------\n\n");
  -    if (IMCC_INFO(interpreter)->verbose ||
  -            (IMCC_INFO(interpreter)->debug & DEBUG_IMC))
  -        imc_stat_init();
  -
  -    /* consecutive labels, if_branch, unused_labels ... */
  -    pre_optimize(interpreter);
  -    if (optimizer_level == OPT_PRE && pasm_file)
  -        return;
  -
  -    nodeStack = imcstack_new();
  -    IMCC_INFO(interpreter)->n_spilled = 0;
  -
  -    todo = first = 1;
  -    while (todo) {
  -        find_basic_blocks(interpreter, first);
  -        build_cfg(interpreter);
  -
  -        if (first && (IMCC_INFO(interpreter)->debug & DEBUG_CFG))
  -            dump_cfg(interpreter);
  -        first = 0;
  -        todo = cfg_optimize(interpreter);
  -    }
  -
  -    todo = first = 1;
  -    while (todo) {
  -        if (!first) {
  -            find_basic_blocks(interpreter, 0);
  -            build_cfg(interpreter);
  -        }
  -        first = 0;
  -
  -        compute_dominators(interpreter);
  -        find_loops(interpreter);
  -
  -        build_reglist(interpreter, unit);
  -        life_analysis(interpreter);
  -        /* optimize, as long as there is something to do */
  -        if (dont_optimize)
  -            todo = 0;
  -        else {
  -            todo = optimize(interpreter);
  -            if (todo)
  -                pre_optimize(interpreter);
  -        }
  -    }
  -    todo = 1;
  -#if !DOIT_AGAIN_SAM
  -    build_interference_graph(interpreter);
  -#endif
  -    while (todo) {
  -#if DOIT_AGAIN_SAM
  -        build_interference_graph(interpreter);
  -#endif
  -        if (optimizer_level & OPT_SUB)
  -            allocate_wanted_regs();
  -        compute_spilling_costs(interpreter);
  -#ifdef DO_SIMPLIFY
  -        /* simplify until no changes can be made */
  -        while (simplify()) {}
  -#endif
  -        order_spilling();          /* put the remaining items on stack */
  -
  -        to_spill = try_allocate(interpreter);
  -        allocated = 1;
  -
  -        if ( to_spill >= 0 ) {
  -            allocated = 0;
  -            spill(interpreter, unit, to_spill);
  -            /*
  -             * build the new cfg/reglist on the fly in spill() and
  -             * do life analysis there for only the involved regs
  -             */
  -#if DOIT_AGAIN_SAM
  -            find_basic_blocks(interpreter, 0);
  -            build_cfg(interpreter);
  -            build_reglist(interpreter);
  -            life_analysis(interpreter);
  -#endif
  -        }
  -        else {
  -            /* the process is finished */
  -            todo = 0;
  -        }
  -    }
  -    if (optimizer_level & OPT_SUB)
  -        pcc_optimize(interpreter);
  -    if (IMCC_INFO(interpreter)->debug & DEBUG_IMC)
  -        dump_instructions(interpreter);
  -    if (IMCC_INFO(interpreter)->verbose  ||
  -            (IMCC_INFO(interpreter)->debug & DEBUG_IMC))
  -        print_stat(interpreter);
  -    imcstack_free(nodeStack);
  -}
  -
  -void
  -free_reglist(Parrot_Interp interpreter)
  -{
  -    if (interference_graph) {
  -        free(interference_graph);
  -        IMCC_INFO(interpreter)->interference_graph = interference_graph = 0;
  -    }
  -    if (reglist) {
  -        int i;
  -        for (i = 0; i < n_symbols; i++)
  -            free_life_info(interpreter, reglist[i]);
  -        free(reglist);
  -        IMCC_INFO(interpreter)->reglist = reglist = NULL;
  -        IMCC_INFO(interpreter)->n_symbols = n_symbols = 0;
  -    }
  -}
  -
  -/* some statistics about register usage
  - * printed with --verbose --verbose
  - */
  -static void
  -make_stat(int *sets, int *cols)
  -{
  -    /* register usage summary */
  -    char type[] = "INSP";
  -    int i, j;
  -    for(i = 0; i < HASH_SIZE; i++) {
  -        SymReg * r = hash[i];
  -     for(; r; r = r->next)
  -            for (j = 0; j < 4; j++)
  -                if (r->set == type[j] && (r->type & VTREGISTER)) {
  -                    sets[j]++;
  -                    if (cols)
  -                        if (r->color > cols[j])
  -                            cols[j] = r->color;
  -                }
  -    }
  -}
  -static int imcsets[4];
  -/* registes usage of .imc */
  -static void imc_stat_init() {
  -    imcsets[0] = imcsets[1] = imcsets[2] = imcsets[3] = 0;
  -    make_stat(imcsets, 0);
  -    memset(&ostat, 0, sizeof(ostat));
  -}
  -
  -/* and final */
  -static void print_stat(Parrot_Interp interpreter)
  -{
  -    int sets[4] = {0,0,0,0};
  -    int cols[4] = {-1,-1,-1,-1};
  -
  -    make_stat(sets, cols);
  -    info(interpreter, 1, "sub %s:\n\tregisters in .imc:\t I%d, N%d, S%d, P%d\n",
  -            function, imcsets[0], imcsets[1], imcsets[2], imcsets[3]);
  -    info(interpreter, 1, "\t%d labels, %d lines deleted, %d if_branch, %d 
branch_branch\n",
  -            ostat.deleted_labels, ostat.deleted_ins, ostat.if_branch,
  -            ostat.branch_branch);
  -    info(interpreter, 1, "\t%d used once deleted\n",
  -            ostat.used_once);
  -    info(interpreter, 1, "\t%d invariants_moved\n", ostat.invariants_moved);
  -    info(interpreter, 1, "\tregisters needed:\t I%d, N%d, S%d, P%d\n",
  -            sets[0], sets[1], sets[2], sets[3]);
  -    info(interpreter, 1, "\tregisters in .pasm:\t I%d, N%d, S%d, P%d - %d 
spilled\n",
  -            cols[0]+1, cols[1]+1, cols[2]+1, cols[3]+1,
  -            IMCC_INFO(interpreter)->n_spilled);
  -    info(interpreter, 1, "\t%d basic_blocks, %d edges\n",
  -            IMCC_INFO(interpreter)->n_basic_blocks, edge_count(interpreter));
  -
  -}
  -
  -/* sort list by line  nr */
  -static int
  -reg_sort_f(const void *a, const void *b) {
  -    SymReg *ra = *(SymReg**) a;
  -    SymReg *rb = *(SymReg**) b;
  -    if (ra->first_ins->index < rb->first_ins->index) {
  -     return -1;
  -    }
  -    else if (ra->first_ins->index == rb->first_ins->index) {
  -        return 0;
  -    }
  -    else {
  -     return 1;
  -    }
  -}
  -
  -static void
  -sort_reglist(void)
  -{
  -    qsort(reglist, n_symbols, sizeof(SymReg*), reg_sort_f);
  -}
  -/* make a linear list of IDENTs and VARs, set n_symbols */
  -
  -static void
  -build_reglist(Parrot_Interp interpreter, Instruction * unit)
  -{
  -    int i, count, unused;
  -
  -    info(interpreter, 2, "build_reglist\n");
  -    /* count symbols */
  -    if (reglist)
  -        free_reglist(interpreter);
  -    for(i = count = 0; i < HASH_SIZE; i++) {
  -        SymReg * r = hash[i];
  -        for(; r; r = r->next)
  -            if(r->type & VTREGISTER)
  -                count++;
  -    }
  -    n_symbols = count;
  -    if (count == 0)
  -        return;
  -    if (n_symbols >= HASH_SIZE)
  -        warning(interpreter, "build_reglist", "probably too small HASH_SIZE"
  -                " (%d symbols)\n");
  -    reglist = calloc(n_symbols, sizeof(SymReg*));
  -    if (reglist == NULL) {
  -        fatal(1, "build_reglist","Out of mem\n");
  -    }
  -    IMCC_INFO(interpreter)->reglist = reglist;
  -
  -    for(i = count = 0; i < HASH_SIZE; i++) {
  -        SymReg * r = hash[i];
  -        /* Add each symbol to reglist  */
  -        for(; r; r = r->next) {
  -            if(r->type & VTREGISTER) {
  -                if (r->type & VT_REGP)
  -                    reglist[count++] = r->reg;
  -                else
  -                    reglist[count++] = r;
  -                /* rearange I/N registers
  -                 * XXX not here, do it, when reading the source
  -                 * .nciarg, ... !!!1 */
  -                if ((optimizer_level & OPT_PASM) && pasm_file &&
  -                        (reglist[count-1]->set == 'I' ||
  -                        reglist[count-1]->set == 'N'))
  -                    reglist[count-1]->color = -1;
  -            }
  -        }
  -    }
  -    compute_du_chain(unit);
  -    /* we might have unused symbols here, from spilling */
  -    for (i = count = unused = 0; i < n_symbols; i++) {
  -        if (!reglist[i]->first_ins)
  -            unused++;
  -        else if (i == count)
  -            count++;
  -        else
  -            reglist[count++] = reglist[i];
  -    }
  -    n_symbols -= unused;
  -    IMCC_INFO(interpreter)->n_symbols = n_symbols;
  -    sort_reglist();
  -}
  -
  -/* creates the interference graph between the variables.
  - *
  - * two variables interfere when they are alive at the
  - * same time
  - */
  -
  -static void
  -build_interference_graph(Parrot_Interp interpreter)
  -{
  -    int x, y;
  -
  -    if (!n_symbols)
  -        return;
  -
  -    /* Construct a graph N x N where N = number of symbolics.
  -     * This piece can be rewritten without the N x N array
  -     */
  -    interference_graph = calloc(n_symbols * n_symbols, sizeof(SymReg*));
  -    if (interference_graph == NULL)
  -        fatal(1, "build_interference_graph","Out of mem\n");
  -    IMCC_INFO(interpreter)->interference_graph = interference_graph;
  -
  -    /* Calculate interferences between each chain and populate the the Y-axis */
  -    for (x = 0; x < n_symbols; x++) {
  -        /* If symbol was never used in a statment, it can't interfere */
  -        if (!reglist[x]->first_ins)
  -            continue;
  -        for (y = x + 1; y < n_symbols; y++) {
  -            if (!reglist[y]->first_ins)
  -                continue;
  -            if (interferes(interpreter, reglist[x], reglist[y])) {
  -                interference_graph[x*n_symbols+y] = reglist[y];
  -                interference_graph[y*n_symbols+x] = reglist[x];
  -            }
  -        }
  -    }
  -
  -    if (IMCC_INFO(interpreter)->debug & DEBUG_IMC)
  -        dump_interference_graph(interpreter);
  -}
  -
  -
  -static void compute_one_du_chain(SymReg * r, Instruction * unit);
  -/* Compute a DU-chain for each symbolic in a compilation unit
  - */
  -static void
  -compute_du_chain(Instruction * unit) {
  -    Instruction * ins, *lastbranch;
  -    int i;
  -
  -    lastbranch = 0;
  -
  -    /* Compute last branch in this procedure, update instruction index */
  -    for(i = 0, ins = unit; ins; ins = ins->next) {
  -        ins->index = i++;
  -        if(ins->type == ITBRANCH)
  -            lastbranch = ins;
  -    }
  -
  -    /* Compute du-chains for all symbolics */
  -    for(i = 0; i < n_symbols; i++) {
  -        SymReg * r = reglist[i];
  -        compute_one_du_chain(r, unit);
  -        /* what is this used for? -lt */
  -        if(r->type == VTIDENTIFIER
  -                && lastbranch
  -                && r->last_ins
  -                && r->last_ins->index < lastbranch->index)
  -            r->last_ins = lastbranch;
  -    }
  -}
  -
  -static void
  -compute_one_du_chain(SymReg * r, Instruction * unit)
  -{
  -    Instruction * ins;
  -
  -    /* We cannot rely on computing the value of r->first when parsing,
  -     * since the situation can be changed at any time by the register
  -     * allocation algorithm
  -     */
  -
  -    r->first_ins = 0;
  -    r->use_count = r->lhs_use_count = 0;
  -    for(ins = unit; ins; ins = ins->next) {
  -        int ro, rw;
  -        ro = instruction_reads(ins, r);
  -        rw = instruction_writes(ins, r);
  -        if(ro || rw) {
  -            if (!r->first_ins) {
  -                r->first_ins = ins;
  -            }
  -            r->last_ins = ins;
  -            if (rw)
  -                r->lhs_use_count++;
  -            r->use_count++;
  -            /* if this symbol is used in a different scope
  -             * assume usage
  -             */
  -            if (r->reg) {
  -                r->lhs_use_count++;
  -                r->use_count++;
  -            }
  -        }
  -    }
  -}
  -
  -/* Computes the cost of spilling each symbol. This is estimated by the number
  - * of times the symbol appears, weighted by X*loop_depth */
  -
  -static void
  -compute_spilling_costs (Parrot_Interp interpreter) {
  -    int depth, i, j, k, max_depth;
  -    SymReg *r;
  -    Instruction * ins;
  -
  -    for(i = 0; i < n_symbols; i++) {
  -        r = reglist[i];
  -        r->score = r->use_count + (r->lhs_use_count << 2);
  -        /* TODO score high if -Oj and register is used in
  -         * JITtable instruction
  -         */
  -        /* r->score *= (r->jit_usage - r->use_count + 1) */
  -        /* TODO rewrite this O(n_ins * n_reg) alg:
  -         * - store max_depth in reg
  -         * - store a flag, when this reg was already spilled
  -         */
  -        for (j = max_depth = 0; j < IMCC_INFO(interpreter)->n_basic_blocks;
  -                j++) {
  -            Life_range *l;
  -            int used = 0;
  -
  -            l = r->life_info[j];
  -            if (!l->first_ins)
  -                continue;
  -            for (ins = l->first_ins ; ins; ins = ins->next) {
  -                for (k = 0; k < IMCC_MAX_REGS && ins->r[k]; k++)
  -                    if (ins->r[k] == r) {
  -                        used = 1;
  -                        break;
  -                    }
  -                if (used && r->usage & U_SPILL) {
  -                    r->score = 100000;
  -                    goto done;
  -                }
  -                if (ins == l->last_ins)
  -                    break;
  -            }
  -
  -            if (used) {
  -                depth = IMCC_INFO(interpreter)->bb_list[j]->loop_depth;
  -                if (depth > max_depth)
  -                    max_depth = depth;
  -            }
  -        }
  -        r->score += 1000 * max_depth;
  -done:
  -        ; /* for MSVC 5 */
  -    }
  -
  -    if (IMCC_INFO(interpreter)->debug & DEBUG_IMC)
  -        dump_symreg(interpreter);
  -
  -}
  -/* See if r0's chain interferes with r1. */
  -/* We currently decide that two vars interfere if they are both alive
  - * at any point. This could be improved, requiring that one is alive
  - * at the point of _definition_ of the other.
  - */
  -
  -static int
  -interferes(Parrot_Interp interpreter, SymReg * r0, SymReg * r1) {
  -
  -    int i;
  -
  -    /* Register doesn't interfere with itself
  -    */
  -    if (r0 == r1)
  -        return 0;
  -
  -    /* different register sets don't interfer */
  -    if (r0->set != r1->set)
  -        return 0;
  -    /* if the first time r0 appears is after (or in the same instruction)
  -     * than the last appearance of r1, then they can't interfere.
  -     *
  -     * even if r0 and r1 are called in the same instruction, and even
  -     * if this instrucion does modify r0, if it's value is never used
  -     * later, then they can share the same register
  -     */
  -
  -    /* Now: */
  -
  -    if (r0->life_info == NULL || r1->life_info == NULL) {
  -        fatal(1, "interferes", "INTERNAL ERROR: Life range is NULL\n");
  -    }
  -
  -    for (i=0; i < IMCC_INFO(interpreter)->n_basic_blocks; i++) {
  -        Life_range *l0, *l1;
  -
  -        l0 = r0->life_info[i];
  -        l1 = r1->life_info[i];
  -
  -        /* one or both are not alive in this block, so we have
  -         * no conflict
  -         */
  -        if (!l0->first_ins || !l1->first_ins)
  -            continue;
  -
  -        /* if the registers don't overlap, i.e first_x > last_y
  -         * then no interference
  -         */
  -        if (l0->first_ins->index > l1->last_ins->index)
  -            continue;
  -        if (l1->first_ins->index > l0->last_ins->index)
  -            continue;
  -
  -#if 1
  -        /* if they only overlap one instruction and one is used RHS only
  -         * and the other LHS, then that's ok
  -         * same if both are LHS
  -         */
  -        if (l0->first_ins->index == l1->last_ins->index &&
  -                instruction_writes(l0->first_ins, r0) &&
  -                instruction_reads(l1->last_ins, r1) &&
  -                !instruction_reads(l0->first_ins, r0))
  -            continue;
  -        if (l1->first_ins->index == l0->last_ins->index &&
  -                instruction_writes(l1->first_ins, r1) &&
  -                instruction_reads(l0->last_ins, r0) &&
  -                !instruction_reads(l1->first_ins, r1))
  -            continue;
  -#endif
  -
  -        return 1;
  -    }
  -
  -    return 0;
  -}
  -
  -/*
  - * Simplify deletes all the nodes from the interference graph
  - * that have arity lower than MAX_COLOR
  - *
  - * Returns if it has been able to delete at least one node
  - * and 0 otherwise.
  - *
  - * XXX: this doesn't look at score, so I think this is bogus
  - *      - currently disabled
  - *
  - */
  -#ifdef DO_SIMPLIFY
  -static int
  -simplify () {
  -    int changes = 0;
  -    int x;
  -    SymReg **g;
  -
  -    g = reglist;
  -
  -    for(x = 0; x < n_symbols; x++) {
  -        if (g[x]->color >= 0)   /* VTPASM */
  -            g[x]->simplified = 1;
  -    }
  -    for(x = 0; x < n_symbols; x++) {
  -     if (g[x]->simplified) {
  -            break;
  -     }
  -
  -     if ( neighbours(x) < MAX_COLOR) {
  -            debug(interpreter, DEBUG_IMC, "#simplifying [%s]\n", g[x]->name);
  -
  -         imcstack_push(nodeStack, x);
  -
  -         g[x]->simplified = 1;
  -         changes = 1;
  -         break;
  -     }
  -    }
  -
  -    return changes;
  -}
  -#endif
  -
  -/* Puts the remaining nodes on the stack, on the correct order.
  - *
  - * We count how many times does a symbol appear (weighted by the probability
  - * that this particular point of code will be reached) and choose the symbol
  - * with the lower score until all are in the stack.
  - *
  - */
  -
  -static void
  -order_spilling () {
  -    int min_score = 0, total_score;
  -    int min_node;
  -    int x;
  -
  -    while (1) {
  -
  -     min_node = -1;
  -
  -        for(x = 0; x < n_symbols; x++) {
  -
  -            /* for now, our score function only
  -            takes in account how many times a symbols
  -            has appeared + the loop_depth */
  -
  -          /* we have to combine somehow the rank of the node
  -           * with the cost of spilling it
  -           *
  -           * our current function to maximize is:
  -           *      rank - spill_cost
  -           *
  -           * I have no clue of how good it is
  -          */
  -         if (!(reglist[x]->simplified)) {
  -             total_score = reglist[x]->score - neighbours(x);
  -
  -                if ( (min_node == -1) || (min_score > total_score) )  {
  -                min_node  = x;
  -                min_score = total_score;
  -             }
  -         }
  -        }
  -
  -     if (min_node == -1) return; /* We are finished */
  -
  -     imcstack_push(nodeStack, min_node);
  -     reglist[min_node]->simplified = 1;
  -    }
  -}
  -
  -
  -static void
  -restore_interference_graph() {
  -    int i;
  -    for (i=0; i < n_symbols; i++) {
  -        if ((reglist[i]->type & VTPASM) && !(optimizer_level & OPT_PASM))
  -            continue;
  -     reglist[i]->color = -1;
  -     reglist[i]->simplified = 0;
  -    }
  -}
  -
  -/*
  - * try to allocate as much as possible
  - */
  -static void
  -allocate_wanted_regs(void)
  -{
  -    int i, y, interf;
  -    SymReg *r, *s;
  -    SymReg ** graph = interference_graph;
  -
  -    for (i = 0; i < n_symbols; i++) {
  -        r = reglist[i];
  -        if (r->color >= 0 || r->want_regno == -1)
  -            continue;
  -        interf = 0;
  -        for (y = 0; y < n_symbols; y++) {
  -            if ((s = graph[i*n_symbols+y])
  -                    && s->color == r->want_regno
  -                    && s->set == r->set) {
  -                interf = 1;
  -            }
  -        }
  -        if (!interf)
  -            r->color = r->want_regno;
  -    }
  -}
  -/*
  - * Color the graph assigning registers to each symbol:
  - *
  - * We just proceed poping items from the stack, and assigning
  - * a free color to the them.
  - *
  - * If we run out of colors, then we need to spill the top node.
  - */
  -
  -static int
  -try_allocate(Parrot_Interp interpreter) {
  -    int x = 0;
  -    int color, colors[MAX_COLOR];
  -    int free_colors, t;
  -    SymReg ** graph = interference_graph;
  -
  -    while ((imcstack_depth(nodeStack) > 0) ) {
  -     x=imcstack_pop(nodeStack);
  -
  -     for (t = 0; t < 4; t++) {
  -         int typ = "INSP"[t];
  -         memset(colors, 0, sizeof(colors));
  -         if (reglist[x]->set == typ && reglist[x]->color == -1) {
  -             free_colors = map_colors(x, graph, colors, typ);
  -             if (free_colors > 0) {
  -                 for (color = 0; color < MAX_COLOR; color++) {
  -                        int c = (color + 16) % 32;
  -                     if (!colors[c]) {
  -                         reglist[x]->color = c;
  -
  -                            debug(interpreter, DEBUG_IMC,
  -                                    "#[%s] provisionally gets color [%d]"
  -                                     "(%d free colors, score %d)\n",
  -                                     reglist[x]->name, c,
  -                                        free_colors, reglist[x]->score);
  -                         break;
  -                     }
  -                 }
  -             }
  -
  -             if (reglist[x]->color == -1) {
  -                    debug(interpreter, DEBUG_IMC, "# no more colors free = %d\n", 
free_colors);
  -
  -                 /* It has been impossible to assign a color
  -                     * to this node, return it so it gets spilled
  -                     */
  -
  -                 restore_interference_graph();
  -                 /* clean stack */
  -                 while ((imcstack_depth(nodeStack) > 0) )
  -                     imcstack_pop(nodeStack);
  -                 return x;
  -             }
  -         }
  -     }
  -    }
  -
  -    return -1; /* we are totally finished */
  -}
  -
  -/*
  - * map_colors: calculates what colors can be assigned to the x-th symbol.
  - */
  -static int
  -map_colors(int x, SymReg ** graph, int colors[], int typ) {
  -    int y = 0;
  -    SymReg * r;
  -    int color, free_colors;
  -    memset(colors, 0, sizeof(colors[0]) * MAX_COLOR);
  -    /* reserved for spilling */
  -    if (typ == 'P')
  -        colors[31] = 1;
  -    for(y = 0; y < n_symbols; y++) {
  -        if((r = graph[x*n_symbols+y])
  -         && r->color != -1
  -         && r->set == typ) {
  -         colors[r->color] = 1;
  -     }
  -    }
  -    for(color = free_colors = 0; color < MAX_COLOR; color++)
  -     if(!colors[color])
  -         free_colors++;
  -    return free_colors;
  -}
  -
  -#if ! DOIT_AGAIN_SAM
  -/* update bb and life_info after spilling
  - * this saves 4 costy routines
  - * NOTE {lhs_,}use_count are not set again, this is save, when no
  - *      further optimization pass follows
  - *
  - */
  -static void
  -update_life(Parrot_Interp interpreter, Instruction * unit, Instruction *ins,
  -        SymReg *r, int needs_fetch, int needs_store, int add)
  -{
  -    Life_range *l;
  -    int i;
  -    Instruction *ins2;
  -    Basic_block **bb_list = IMCC_INFO(interpreter)->bb_list;
  -
  -    for(i = 0, ins2 = unit; ins2; ins2 = ins2->next) {
  -        ins2->index = i++;
  -    }
  -    /* add this sym to reglist, if not there */
  -    if (add) {
  -        reglist = realloc(reglist, (n_symbols + 1) * sizeof(SymReg *));
  -        reglist[n_symbols++] = r;
  -    }
  -
  -    r->first_ins = r->last_ins = ins;
  -    if (needs_fetch) {
  -        /* prev instructions is a fetch then and the first usage of this reg */
  -        r->first_ins = ins->prev;
  -        /* if this ins was the first of a BB, then the fetch is the
  -         * first ins then
  -         */
  -        if (ins == bb_list[ins->bbindex]->start)
  -            bb_list[ins->bbindex]->start = ins->prev;
  -    }
  -    if (needs_store) {
  -        /* next ins is a store then, and ends life of this reg */
  -        r->last_ins = ins->next;
  -        if (ins == bb_list[ins->bbindex]->end)
  -            bb_list[ins->bbindex]->end = ins->next;
  -    }
  -    /* now set life_info */
  -    free_life_info(interpreter, r);
  -    r->life_info = calloc(IMCC_INFO(interpreter)->n_basic_blocks,
  -            sizeof(Life_range*));
  -    for (i=0; i < IMCC_INFO(interpreter)->n_basic_blocks; i++)
  -        make_life_range(r, i);
  -    l = r->life_info[ins->bbindex];
  -    l->first_ins = r->first_ins;
  -    l->last_ins = r->last_ins;
  -    if (IMCC_INFO(interpreter)->debug & DEBUG_IMC) {
  -        dump_instructions(interpreter);
  -        dump_symreg(interpreter);
  -    }
  -}
  -/*
  - * update the interference_graph too and don't call
  - *      build_interference_graph again
  - */
  -
  -static void
  -update_interference(Parrot_Interp interpreter, SymReg *old, SymReg *new)
  -{
  -    int x, y;
  -    if (old != new) {
  -        /* n_symbols is already increased */
  -        SymReg ** new_graph = calloc(n_symbols * n_symbols, sizeof(SymReg*));
  -        /* old symbols count of previous graph */
  -        int o = n_symbols - 1;
  -        for (x = 0; x < o; x++) {
  -            for (y = x + 1; y < o; y++) {
  -                new_graph[x*n_symbols+y] = interference_graph[x*o+y];
  -                new_graph[y*n_symbols+x] = interference_graph[y*o+x];
  -            }
  -        }
  -        free(interference_graph);
  -        interference_graph = new_graph;
  -    }
  -    for (x = 0; x < n_symbols; x++) {
  -        for (y = x + 1; y < n_symbols; y++) {
  -            if (reglist[x] == old || reglist[x] == new ||
  -                    reglist[y] == old || reglist[y] == new) {
  -                if (interferes(interpreter, reglist[x], reglist[y])) {
  -                    interference_graph[x*n_symbols+y] = reglist[y];
  -                    interference_graph[y*n_symbols+x] = reglist[x];
  -                }
  -                else {
  -                    interference_graph[x*n_symbols+y] = NULL;
  -                    interference_graph[y*n_symbols+x] = NULL;
  -                }
  -            }
  -        }
  -    }
  -    if (IMCC_INFO(interpreter)->debug & DEBUG_IMC) {
  -        dump_interference_graph(interpreter);
  -    }
  -}
  -#endif
  -
  -/* Rewrites the unit instructions, inserting spill code in every ocurrence
  - * of the symbol.
  - */
  -
  -static void
  -spill(struct Parrot_Interp *interpreter, Instruction * unit, int spilled)
  -{
  -    Instruction * tmp, *ins;
  -    int i, n, dl;
  -    int needs_fetch, needs_store;
  -    SymReg * old_sym, *p31, *new_sym;
  -    char * buf;
  -    SymReg *regs[IMCC_MAX_REGS];
  -
  -    buf = malloc(256 * sizeof(char));
  -    if (buf == NULL) {
  -     fatal(1, "spill","Out of mem\n");
  -    }
  +    /* Not much here for now except the allocator */
   
  -    debug(interpreter, DEBUG_IMC, "#Spilling [%s]:\n", reglist[spilled]->name);
  -
  -    new_sym = old_sym = reglist[spilled];
  -    if (old_sym->usage & U_SPILL)
  -        fatal(1, "spill", "double spill - program too complex\n");
  -    new_sym->usage |= U_SPILL;
  -
  -    IMCC_INFO(interpreter)->n_spilled++;
  -    n = 0;
  -    dl = 0;     /* line corr */
  -    tmp = NULL;
  -
  -
  -    /* first instruction should be ".sub" -- make sure we allocate P31
  -     * _after_ subroutine entry.  And after the "saveall", or any
  -     * other assortment of pushes. */
  -
  -    if (!IMCC_INFO(interpreter)->p31) {
  -        Instruction *spill_ins;
  -
  -        p31 = IMCC_INFO(interpreter)->p31 = mk_pasm_reg(str_dup("P31"));
  -        ins = unit;
  -        while (ins
  -                && (strncmp(ins->fmt, "push", 4) == 0
  -                    || strcmp(ins->fmt, "saveall") == 0)) {
  -            ins = ins->next;
  -        }
  -        spill_ins = iNEW(interpreter, p31, str_dup("PerlArray"), NULL, 0);
  -        insert_ins(ins, spill_ins);
  -    }
  -    else
  -        p31 = IMCC_INFO(interpreter)->p31;
  -
  -    for(ins = unit; ins; ins = ins->next) {
  -     needs_store = 0;
  -     needs_fetch = 0;
  -
  -     if (instruction_reads (ins, old_sym) && !(ins->flags & ITSPILL))
  -         needs_fetch = 1;
  -
  -     if (instruction_writes (ins, old_sym) && !(ins->flags & ITSPILL))
  -         needs_store = 1;
  -        if (dl)
  -            ins->index += dl;
  -
  -     if (needs_fetch) {
  -         regs[0] = new_sym;
  -            regs[1] = p31;
  -            sprintf(buf, "%d", IMCC_INFO(interpreter)->n_spilled);
  -            regs[2] = mk_const(str_dup(buf), 'I');
  -         sprintf(buf, "%%s, %%s[%%s] #FETCH %s", old_sym->name);
  -         tmp = INS(interpreter, "set", buf, regs, 3, 4, 0);
  -         tmp->bbindex = ins->bbindex;
  -            tmp->flags |= ITSPILL;
  -            tmp->index = ins->index;
  -            ins->index++;
  -            /* insert tmp before actual ins */
  -            insert_ins(ins->prev, tmp);
  -            dl++;
  -     }
  -        /* change all occurance of old_sym to new */
  -        for (i = 0; old_sym != new_sym && ins->r[i] &&
  -                i < IMCC_MAX_REGS; i++)
  -            if (ins->r[i] == old_sym)
  -                ins->r[i] = new_sym;
  -     if (needs_store) {
  -            regs[0] = p31;
  -            sprintf(buf, "%d", IMCC_INFO(interpreter)->n_spilled);
  -            regs[1] = mk_const(str_dup(buf), 'I');
  -         regs[2] = new_sym;
  -         sprintf(buf, "%%s[%%s], %%s #STORE %s", old_sym->name);
  -         tmp = INS(interpreter, "set", buf, regs, 3, 2, 0);
  -         tmp->bbindex = ins->bbindex;
  -            tmp->flags |= ITSPILL;
  -            /* insert tmp after ins */
  -            insert_ins(ins, tmp);
  -            tmp->index = ins->index + 1;
  -            dl++;
  -     }
  -        if (needs_fetch || needs_store) {
  -#if ! DOIT_AGAIN_SAM
  -            /* update life info of prev sym */
  -            update_life(interpreter, unit, ins, new_sym, needs_fetch, needs_store,
  -                    old_sym != new_sym);
  -            /* and interference of both */
  -            update_interference(interpreter, old_sym, new_sym);
  -#endif
  -            /* if all symbols are in one basic_block, we need a new
  -             * symbol, so that the life_ranges are minimal
  -             * It would be nice, to detect, when changing the symbol
  -             * is necessary.
  -             */
  -            sprintf(buf, "%s_%d", old_sym->name, n++);
  -            new_sym = mk_symreg(str_dup(buf), old_sym->set);
  -            new_sym->usage |= U_SPILL;
  -            if (needs_store)    /* advance past store */
  -                ins = tmp;
  -        }
  -    }
  -
  -    free(buf);
  -
  -#if DOIT_AGAIN_SAM
  -    /* update index */
  -    for(i = 0, ins = unit; ins; ins = ins->next) {
  -     ins->index = i++;
  -    }
  -#endif
  -    if (IMCC_INFO(interpreter)->debug & DEBUG_IMC)
  -        dump_instructions(interpreter);
  -
  -}
  -
  -static int
  -neighbours(int node) {
  -    int y, cnt;
  -    SymReg *r;
  -
  -    cnt = 0;
  -    for (y = 0; y < n_symbols; y++) {
  -
  -     if ( (r = interference_graph[node*n_symbols + y] ) &&
  -                     (!r->simplified) ) {
  -          cnt++;
  -     }
  -    }
  -
  -    return cnt;
  +    imc_reg_alloc(interpreter, unit);
   }
  -/*
  - * Utility functions
  - */
   
  -
  -char * str_dup(const char * old) {
  -    char * copy = (char *)malloc(strlen(old) + 1);
  -    if (copy == NULL) {
  -        fatal(1, "str_dup", "Out of mem\n");
  -    }
  -    strcpy(copy, old);
  -#ifdef MEMDEBUG
  -    debug(interpreter, 1,"line %d str_dup %s [%x]\n", line, old, copy);
  -#endif
  -    return copy;
  -}
  -
  -char * str_cat(const char * s1, const char * s2) {
  -    int len = strlen(s1) + strlen(s2) + 1;
  -    char * s3 = malloc(len);
  -    if (s3 == NULL) {
  -        fatal(1, "str_cat", "Out of mem\n");
  -    }
  -    strcpy(s3, s1);
  -    strcat(s3, s2);
  -    return s3;
  -}
   
   /*
    * Local variables:
  
  
  
  1.44      +33 -0     parrot/imcc/parser_util.c
  
  Index: parser_util.c
  ===================================================================
  RCS file: /cvs/public/parrot/imcc/parser_util.c,v
  retrieving revision 1.43
  retrieving revision 1.44
  diff -u -w -r1.43 -r1.44
  --- parser_util.c     27 Oct 2003 07:45:04 -0000      1.43
  +++ parser_util.c     4 Nov 2003 00:37:30 -0000       1.44
  @@ -705,6 +705,39 @@
   }
   
   /*
  + * Utility functions
  + */
  +
  +char *
  +str_dup(const char * old)
  +{
  +    char * copy = (char *)malloc(strlen(old) + 1);
  +    if (copy == NULL) {
  +        fatal(1, "str_dup", "Out of mem\n");
  +    }
  +    strcpy(copy, old);
  +#ifdef MEMDEBUG
  +    debug(interpreter, 1,"line %d str_dup %s [%x]\n", line, old, copy);
  +#endif
  +    return copy;
  +}       
  +    
  +char *
  +str_cat(const char * s1, const char * s2)
  +{
  +    int len = strlen(s1) + strlen(s2) + 1;
  +    char * s3 = malloc(len);
  +    if (s3 == NULL) {
  +        fatal(1, "str_cat", "Out of mem\n");
  +    }
  +    strcpy(s3, s1);
  +    strcat(s3, s2);
  +    return s3;
  +}   
  +
  +
  +
  +/*
    * Local variables:
    * c-indentation-style: bsd
    * c-basic-offset: 4
  
  
  

Reply via email to