2008-03-20 Mark Probst <mark.probst@gmail.com>
[mono.git] / mono / mini / ssa.c
index c8718a74107be5ae0c3851646ab542a129414ebc..134e16caf33c490d6c2b8426d76dc48127128bf7 100644 (file)
@@ -11,6 +11,8 @@
 
 #include "mini.h"
 
+#ifndef DISABLE_SSA
+
 #define USE_ORIGINAL_VARS
 #define CREATE_PRUNED_SSA
 
@@ -195,14 +197,14 @@ mono_ssa_rename_vars (MonoCompile *cfg, int max_vars, MonoBasicBlock *bb, MonoIn
 {
        MonoInst *inst, *new_var;
        int i, j, idx;
-       GList *tmp;
+       GSList *tmp;
        MonoInst **new_stack;
 
 #ifdef DEBUG_SSA
        printf ("RENAME VARS BB%d %s\n", bb->block_num, mono_method_full_name (cfg->method, TRUE));
 #endif
 
-       for (inst = bb->code; inst; inst = inst->next) {
+       MONO_BB_FOR_EACH_INS (bb, inst) {
                if (inst->opcode != OP_PHI)
                        replace_usage (cfg, bb, inst, stack);
 
@@ -223,7 +225,7 @@ mono_ssa_rename_vars (MonoCompile *cfg, int max_vars, MonoBasicBlock *bb, MonoIn
                        inst->inst_i0 = new_var;
 
 #ifdef USE_ORIGINAL_VARS
-                       cfg->vars [new_var->inst_c0]->reg = idx;
+                       MONO_VARINFO (cfg, new_var->inst_c0)->reg = idx;
 #endif
 
                        stack [idx] = new_var;
@@ -237,7 +239,7 @@ mono_ssa_rename_vars (MonoCompile *cfg, int max_vars, MonoBasicBlock *bb, MonoIn
                        if (n->in_bb [j] == bb)
                                break;
                
-               for (inst = n->code; inst; inst = inst->next) {
+               MONO_BB_FOR_EACH_INS (n, inst) {
                        if (inst->ssa_op == MONO_SSA_STORE && inst->inst_i1->opcode == OP_PHI) {
                                idx = inst->inst_i1->inst_c0;
                                if (stack [idx])
@@ -294,7 +296,7 @@ mono_ssa_compute (MonoCompile *cfg)
                mono_bitset_set (vinfo [i].def_in, 0);
        }
        for (i = 0; i < cfg->num_bblocks; ++i) {
-               for (inst = cfg->bblocks [i]->code; inst; inst = inst->next) {
+               MONO_BB_FOR_EACH_INS (cfg->bblocks [i], inst) {
                        if (inst->ssa_op == MONO_SSA_STORE) {
                                idx = inst->inst_i0->inst_c0;
                                g_assert (idx < cfg->num_varinfo);
@@ -334,10 +336,7 @@ mono_ssa_compute (MonoCompile *cfg)
                        store->inst_i1 = inst;
                        store->klass = store->inst_i0->klass;
             
-                       store->next = bb->code;
-                       bb->code = store;
-                       if (!bb->last_ins)
-                               bb->last_ins = bb->code;
+                       MONO_INST_LIST_ADD (&store->node, &bb->ins_list);
 
 #ifdef DEBUG_SSA
                        printf ("ADD PHI BB%d %s\n", cfg->bblocks [idx]->block_num, mono_method_full_name (cfg->method, TRUE));
@@ -420,7 +419,7 @@ mono_ssa_replace_copies (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, c
            (inst->inst_i0->opcode == OP_LOCAL || inst->inst_i0->opcode == OP_ARG)) {
                MonoInst *new_var;
                int idx = inst->inst_i0->inst_c0;
-               MonoMethodVar *mv = cfg->vars [idx];
+               MonoMethodVar *mv = MONO_VARINFO (cfg, idx);
 
                if (mv->reg != -1 && mv->reg != mv->idx) {
                       
@@ -448,7 +447,7 @@ mono_ssa_replace_copies (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, c
        if (inst->ssa_op == MONO_SSA_STORE && inst->inst_i1->ssa_op == MONO_SSA_LOAD &&
            inst->inst_i0->inst_c0 == inst->inst_i1->inst_i0->inst_c0) {
                inst->ssa_op = MONO_SSA_NOP;
-               inst->opcode = CEE_NOP;
+               inst->opcode = OP_NOP;
        }
 
 }
@@ -467,7 +466,7 @@ mono_ssa_remove (MonoCompile *cfg)
 
        for (i = 0; i < cfg->num_bblocks; ++i) {
                MonoBasicBlock *bb = cfg->bblocks [i];
-               for (inst = bb->code; inst; inst = inst->next) {
+               MONO_BB_FOR_EACH_INS (bb, inst) {
                        if (inst->ssa_op == MONO_SSA_STORE && inst->inst_i1->opcode == OP_PHI) {
                                
                                phi = inst->inst_i1;
@@ -476,7 +475,7 @@ mono_ssa_remove (MonoCompile *cfg)
                                for (j = 0; j < bb->in_count; j++) {
                                        MonoBasicBlock *pred = bb->in_bb [j];
                                        int idx = phi->inst_phi_args [j + 1];
-                                       MonoMethodVar *mv = cfg->vars [idx];
+                                       MonoMethodVar *mv = MONO_VARINFO (cfg, idx);
 
                                        if (mv->reg != -1 && mv->reg != mv->idx) {
                                                //printf ("PHICOPY %d %d -> %d\n", idx, mv->reg, inst->inst_i0->inst_c0);
@@ -493,7 +492,7 @@ mono_ssa_remove (MonoCompile *cfg)
                                }
 
                                /* remove the phi functions */
-                               inst->opcode = CEE_NOP;
+                               inst->opcode = OP_NOP;
                                inst->ssa_op = MONO_SSA_NOP;
                        } 
                }
@@ -554,13 +553,13 @@ mono_ssa_remove (MonoCompile *cfg)
        for (i = 0; i < cfg->num_bblocks; ++i) {
                MonoBasicBlock *bb = cfg->bblocks [i];
 
-               for (inst = bb->code; inst; inst = inst->next)
+               MONO_BB_FOR_EACH_INS (bb, inst)
                        mono_ssa_replace_copies (cfg, bb, inst, is_live);
        }
 
        for (i = 0; i < cfg->num_varinfo; ++i) {
-               cfg->vars [i]->reg = -1;
-               if (!is_live [i]) {
+               MONO_VARINFO (cfg, i)->reg = -1;
+               if (!is_live [i] && !(cfg->varinfo [i]->flags & MONO_INST_VOLATILE)) {
                        cfg->varinfo [i]->flags |= MONO_INST_IS_DEAD;
                }
        }
@@ -572,7 +571,7 @@ mono_ssa_remove (MonoCompile *cfg)
 }
 
 
-#define IS_CALL(op) (op == CEE_CALLI || op == CEE_CALL || op == CEE_CALLVIRT || (op >= OP_VOIDCALL && op <= OP_CALL_MEMBASE))
+#define IS_CALL(op) (op == CEE_CALLI || op == OP_CALL || op == OP_CALLVIRT || (op >= OP_VOIDCALL && op <= OP_CALL_MEMBASE))
 
 typedef struct {
        MonoBasicBlock *bb;
@@ -614,7 +613,7 @@ analyze_dev_use (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *root, MonoInst
        if ((inst->ssa_op == MONO_SSA_STORE) && 
            (inst->inst_i0->opcode == OP_LOCAL /*|| inst->inst_i0->opcode == OP_ARG */)) {
                idx = inst->inst_i0->inst_c0;
-               info = cfg->vars [idx];
+               info = MONO_VARINFO (cfg, idx);
                //printf ("%d defined in BB%d %p\n", idx, bb->block_num, root);
                if (info->def) {
                        g_warning ("more than one definition of variable %d in %s", idx,
@@ -631,7 +630,7 @@ analyze_dev_use (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *root, MonoInst
                        for (i = inst->inst_i1->inst_phi_args [0]; i > 0; i--) {
                                MonoVarUsageInfo *ui = mono_mempool_alloc (cfg->mempool, sizeof (MonoVarUsageInfo));
                                idx = inst->inst_i1->inst_phi_args [i]; 
-                               info = cfg->vars [idx];
+                               info = MONO_VARINFO (cfg, idx);
                                //printf ("FOUND %d\n", idx);
                                ui->bb = bb;
                                ui->inst = root;
@@ -644,7 +643,7 @@ analyze_dev_use (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *root, MonoInst
            (inst->inst_i0->opcode == OP_LOCAL || inst->inst_i0->opcode == OP_ARG)) {
                MonoVarUsageInfo *ui = mono_mempool_alloc (cfg->mempool, sizeof (MonoVarUsageInfo));
                idx = inst->inst_i0->inst_c0;   
-               info = cfg->vars [idx];
+               info = MONO_VARINFO (cfg, idx);
                //printf ("FOUND %d\n", idx);
                ui->bb = bb;
                ui->inst = root;
@@ -677,10 +676,10 @@ mono_ssa_avoid_copies (MonoCompile *cfg)
        g_assert ((cfg->comp_done & MONO_COMP_SSA_DEF_USE));
 
        for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
-               for (inst = bb->code; inst; inst = inst->next) {
+               MONO_BB_FOR_EACH_INS (bb, inst) {
                        if (inst->ssa_op == MONO_SSA_STORE && inst->inst_i0->opcode == OP_LOCAL &&
                            !IS_CALL (inst->inst_i1->opcode) && inst->inst_i1->opcode != OP_PHI && !inst->flags) {
-                               i1 = cfg->vars [inst->inst_i0->inst_c0];
+                               i1 = MONO_VARINFO (cfg, inst->inst_i0->inst_c0);
 
 /* fixme: compiling mcs does not work when I enable this */
 #if 0
@@ -696,22 +695,27 @@ mono_ssa_avoid_copies (MonoCompile *cfg)
                                                                                                                
                                                //mono_print_tree (u); printf ("\n");
                                                        
-                                               inst->opcode = CEE_NOP;
+                                               inst->opcode = OP_NOP;
                                                inst->ssa_op = MONO_SSA_NOP;
                                        }
                                }
 #endif                 
-                               if ((next = inst->next) && next->ssa_op == MONO_SSA_STORE && next->inst_i0->opcode == OP_LOCAL &&
-                                   next->inst_i1->ssa_op == MONO_SSA_LOAD &&  next->inst_i1->inst_i0->opcode == OP_LOCAL &&
-                                   next->inst_i1->inst_i0->inst_c0 == inst->inst_i0->inst_c0 && g_list_length (i1->uses) == 1 &&
-                                   inst->opcode == next->opcode && inst->inst_i0->type == next->inst_i0->type) {
-                                       i2 = cfg->vars [next->inst_i0->inst_c0];
+                               next = mono_inst_list_next (&inst->node, &bb->ins_list);
+                               if (next && next->ssa_op == MONO_SSA_STORE &&
+                                               next->inst_i0->opcode == OP_LOCAL &&
+                                               next->inst_i1->ssa_op == MONO_SSA_LOAD &&
+                                               next->inst_i1->inst_i0->opcode == OP_LOCAL &&
+                                               next->inst_i1->inst_i0->inst_c0 == inst->inst_i0->inst_c0 &&
+                                               g_list_length (i1->uses) == 1 &&
+                                               inst->opcode == next->opcode &&
+                                               inst->inst_i0->type == next->inst_i0->type) {
+                                       i2 = MONO_VARINFO (cfg, next->inst_i0->inst_c0);
                                        //printf ("ELIM. COPY in BB%d %s\n", bb->block_num, mono_method_full_name (cfg->method, TRUE));
                                        inst->inst_i0 = next->inst_i0;
                                        i2->def = inst;
                                        i1->def = NULL;
                                        i1->uses = NULL;
-                                       next->opcode = CEE_NOP;
+                                       next->opcode = OP_NOP;
                                        next->ssa_op = MONO_SSA_NOP;
                                }
                        }
@@ -728,7 +732,7 @@ mono_ssa_create_def_use (MonoCompile *cfg)
 
        for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
                MonoInst *inst;
-               for (inst = bb->code; inst; inst = inst->next) {
+               MONO_BB_FOR_EACH_INS (bb, inst) {
                        gboolean has_side_effects = analyze_dev_use (cfg, bb, inst, inst);
                        if (has_side_effects && (inst->ssa_op == MONO_SSA_STORE) && 
                                        (inst->inst_i0->opcode == OP_LOCAL || inst->inst_i0->opcode == OP_ARG)) {
@@ -933,14 +937,14 @@ fold_tree (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, MonoInst **carr
                if (target) {
                        bb->out_bb [0] = target;
                        bb->out_count = 1;
-                       inst->opcode = CEE_BR;
+                       inst->opcode = OP_BR;
                        inst->inst_target_bb = target;
                }
-       } else if (inst->opcode == CEE_SWITCH && (evaluate_const_tree (cfg, inst->inst_left, &a, carray) == 1) && (a >= 0) && (a < GPOINTER_TO_INT (inst->klass))) {
+       } else if (inst->opcode == OP_SWITCH && (evaluate_const_tree (cfg, inst->inst_left, &a, carray) == 1) && (a >= 0) && (a < GPOINTER_TO_INT (inst->klass))) {
                bb->out_bb [0] = inst->inst_many_bb [a];
                bb->out_count = 1;
                inst->inst_target_bb = bb->out_bb [0];
-               inst->opcode = CEE_BR;
+               inst->opcode = OP_BR;
        }
 
 }
@@ -970,7 +974,7 @@ visit_inst (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, GList **cvars,
 {
        g_assert (inst);
 
-       if (inst->opcode == CEE_SWITCH) {
+       if (inst->opcode == OP_SWITCH) {
                int r1, i, a;
                int cases = GPOINTER_TO_INT (inst->klass);
 
@@ -992,6 +996,13 @@ visit_inst (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, GList **cvars,
                                }
                        }
                }
+       } else if (inst->opcode == OP_BR) {
+               MonoBasicBlock *target = inst->inst_target_bb;
+
+               if (!(target->flags &  BB_REACHABLE)) {
+                       target->flags |= BB_REACHABLE;
+                       *bblist = g_list_prepend (*bblist, target);
+               }
        } else if ((inst->opcode >= CEE_BEQ && inst->opcode <= CEE_BLT_UN) &&
            ((inst->inst_i0->opcode == OP_COMPARE) || (inst->inst_i0->opcode == OP_LCOMPARE))) {
                int a, b, r1, r2;
@@ -1025,7 +1036,7 @@ visit_inst (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, GList **cvars,
                }       
        } else if (inst->ssa_op == MONO_SSA_STORE && 
                   (inst->inst_i0->opcode == OP_LOCAL || inst->inst_i0->opcode == OP_ARG)) {
-               MonoMethodVar *info = cfg->vars [inst->inst_i0->inst_c0];
+               MonoMethodVar *info = MONO_VARINFO (cfg, inst->inst_i0->inst_c0);
                MonoInst *i1 = inst->inst_i1;
                int res;
                
@@ -1037,7 +1048,7 @@ visit_inst (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, GList **cvars,
                                int j;
 
                                for (j = 1; j <= i1->inst_phi_args [0]; j++) {
-                                       MonoMethodVar *mv = cfg->vars [i1->inst_phi_args [j]];
+                                       MonoMethodVar *mv = MONO_VARINFO (cfg, i1->inst_phi_args [j]);
                                        MonoInst *src = mv->def;
 
                                        if (mv->def_bb && !(mv->def_bb->flags & BB_REACHABLE)) {
@@ -1104,7 +1115,7 @@ mono_ssa_cprop (MonoCompile *cfg)
        memset (carray, 0, sizeof (MonoInst *) * cfg->num_varinfo);
 
        for (i = 0; i < cfg->num_varinfo; i++) {
-               MonoMethodVar *info = cfg->vars [i];
+               MonoMethodVar *info = MONO_VARINFO (cfg, i);
                if (!info->def)
                        info->cpstate = 2;
        }
@@ -1127,9 +1138,8 @@ mono_ssa_cprop (MonoCompile *cfg)
                        }
                }
 
-               for (inst = bb->code; inst; inst = inst->next) {
+               MONO_BB_FOR_EACH_INS (bb, inst)
                        visit_inst (cfg, bb, inst, &cvars, &bblock_list, carray);
-               }
 
                while (cvars) {
                        MonoMethodVar *info = (MonoMethodVar *)cvars->data;                     
@@ -1146,9 +1156,8 @@ mono_ssa_cprop (MonoCompile *cfg)
 
        for (bb = cfg->bb_entry->next_bb; bb; bb = bb->next_bb) {
                MonoInst *inst;
-               for (inst = bb->code; inst; inst = inst->next) {
+               MONO_BB_FOR_EACH_INS (bb, inst)
                        fold_tree (cfg, bb, inst, carray);
-               }
        }
 
        g_free (carray);
@@ -1186,7 +1195,7 @@ mono_ssa_deadce (MonoCompile *cfg)
        /* fixme: we should update usage infos during cprop, instead of computing it again */
        cfg->comp_done &=  ~MONO_COMP_SSA_DEF_USE;
        for (i = 0; i < cfg->num_varinfo; i++) {
-               MonoMethodVar *info = cfg->vars [i];
+               MonoMethodVar *info = MONO_VARINFO (cfg, i);
                info->def = NULL;
                info->uses = NULL;
        }
@@ -1198,7 +1207,7 @@ mono_ssa_deadce (MonoCompile *cfg)
 
        work_list = NULL;
        for (i = 0; i < cfg->num_varinfo; i++) {
-               MonoMethodVar *info = cfg->vars [i];
+               MonoMethodVar *info = MONO_VARINFO (cfg, i);
                work_list = g_list_prepend (work_list, info);
                
                //if ((info->def != NULL) && (info->def->inst_i1->opcode != OP_PHI)) printf ("SSA DEADCE TOTAL LOCAL\n");
@@ -1216,17 +1225,17 @@ mono_ssa_deadce (MonoCompile *cfg)
                        if (i1->opcode == OP_PHI) {
                                int j;
                                for (j = i1->inst_phi_args [0]; j > 0; j--) {
-                                       MonoMethodVar *u = cfg->vars [i1->inst_phi_args [j]];
+                                       MonoMethodVar *u = MONO_VARINFO (cfg, i1->inst_phi_args [j]);
                                        add_to_dce_worklist (cfg, info, u, &work_list);
                                }
                        } else if (i1->ssa_op == MONO_SSA_LOAD &&
                                   (i1->inst_i0->opcode == OP_LOCAL || i1->inst_i0->opcode == OP_ARG)) {
-                                       MonoMethodVar *u = cfg->vars [i1->inst_i0->inst_c0];
+                                       MonoMethodVar *u = MONO_VARINFO (cfg, i1->inst_i0->inst_c0);
                                        add_to_dce_worklist (cfg, info, u, &work_list);
                        }
                        //if (i1->opcode != OP_PHI) printf ("SSA DEADCE DEAD LOCAL\n");
 
-                       info->def->opcode = CEE_NOP;
+                       info->def->opcode = OP_NOP;
                        info->def->ssa_op = MONO_SSA_NOP;
                }
 
@@ -1255,7 +1264,7 @@ mono_ssa_strength_reduction (MonoCompile *cfg)
                                continue;
 
                        for (i = 0; i < cfg->num_varinfo; i++) {
-                               MonoMethodVar *info = cfg->vars [i];
+                               MonoMethodVar *info = MONO_VARINFO (cfg, i);
                        
                                if (info->def && info->def->ssa_op == MONO_SSA_STORE &&
                                    info->def->inst_i0->opcode == OP_LOCAL && g_list_find (lp, info->def_bb)) {
@@ -1269,3 +1278,6 @@ mono_ssa_strength_reduction (MonoCompile *cfg)
        }
 }
 #endif
+
+#endif /* DISABLE_SSA */
+