2008-01-24 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / liveness.c
index dbc3edcb9df1edb01efad82f006cdb6676124ac1..df4c6b07a9bd06242995be7890c57927902c833b 100644 (file)
@@ -21,6 +21,9 @@
 #define BITS_PER_CHUNK 32
 #endif
 
+static void
+optimize_initlocals (MonoCompile *cfg);
+
 /* mono_bitset_mp_new:
  * 
  * allocates a MonoBitSet inside a memory pool
@@ -107,13 +110,6 @@ update_gen_kill_set (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, int i
                                int idx = affected_variable->variable_index;
                                MonoMethodVar *vi = MONO_VARINFO (cfg, idx);
                                g_assert (idx < max_vars);
-                               if ((bb->region != -1) && !MONO_BBLOCK_IS_IN_REGION (bb, MONO_REGION_TRY)) {
-                                       /*
-                                        * Variables used in exception regions can't be allocated to 
-                                        * registers.
-                                        */
-                                       cfg->varinfo [vi->idx]->flags |= MONO_INST_VOLATILE;
-                               }
                                update_live_range (cfg, idx, bb->dfn, inst_num); 
                                if (!mono_bitset_test_fast (bb->kill_set, idx))
                                        mono_bitset_set_fast (bb->gen_set, idx);
@@ -130,13 +126,6 @@ update_gen_kill_set (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, int i
                                g_assert (idx < max_vars);
                                //if (arity > 0)
                                        //g_assert (inst->inst_i1->opcode != OP_PHI);
-                               if ((bb->region != -1) && !MONO_BBLOCK_IS_IN_REGION (bb, MONO_REGION_TRY)) {
-                                       /*
-                                        * Variables used in exception regions can't be allocated to 
-                                        * registers.
-                                        */
-                                       cfg->varinfo [vi->idx]->flags |= MONO_INST_VOLATILE;
-                               }
                                update_live_range (cfg, idx, bb->dfn, inst_num); 
                                mono_bitset_set_fast (bb->kill_set, idx);
                                if (inst->ssa_op == MONO_SSA_STORE)
@@ -145,7 +134,7 @@ update_gen_kill_set (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, int i
                                affected_variable = affected_variable->next;
                        }
                }
-       } else if (inst->opcode == CEE_JMP) {
+       } else if (inst->opcode == OP_JMP) {
                /* Keep arguments live! */
                int i;
                for (i = 0; i < cfg->num_varinfo; i++) {
@@ -208,8 +197,10 @@ visit_bb (MonoCompile *cfg, MonoBasicBlock *bb, GSList **visited)
        if (cfg->aliasing_info != NULL)
                mono_aliasing_initialize_code_traversal (cfg->aliasing_info, bb);
        
-       for (tree_num = 0, inst = bb->code; inst; inst = inst->next, tree_num++) {
+       tree_num = 0;
+       MONO_BB_FOR_EACH_INS (bb, inst) {
                update_volatile (cfg, bb, inst, tree_num);
+               tree_num++;
        }
 
        *visited = g_slist_append (*visited, bb);
@@ -223,8 +214,8 @@ visit_bb (MonoCompile *cfg, MonoBasicBlock *bb, GSList **visited)
        }
 }
 
-static void
-handle_exception_clauses (MonoCompile *cfg)
+void
+mono_liveness_handle_exception_clauses (MonoCompile *cfg)
 {
        MonoBasicBlock *bb;
        GSList *visited = NULL;
@@ -302,11 +293,13 @@ mono_analyze_liveness (MonoCompile *cfg)
                if (cfg->aliasing_info != NULL)
                        mono_aliasing_initialize_code_traversal (cfg->aliasing_info, bb);
                
-               for (tree_num = 0, inst = bb->code; inst; inst = inst->next, tree_num++) {
+               tree_num = 0;
+               MONO_BB_FOR_EACH_INS (bb, inst) {
 #ifdef DEBUG_LIVENESS
                        mono_print_tree (inst); printf ("\n");
 #endif
                        update_gen_kill_set (cfg, bb, inst, tree_num);
+                       tree_num++;
                }
 
 #ifdef DEBUG_LIVENESS
@@ -475,15 +468,6 @@ mono_analyze_liveness (MonoCompile *cfg)
                }
        }
 
-       /* todo: remove code when we have verified that the liveness for try/catch blocks
-        * works perfectly 
-        */
-       /* 
-        * Currently, this can't be commented out since exception blocks are not
-        * processed during liveness analysis.
-        */
-       handle_exception_clauses (cfg);
-
        /*
         * Arguments need to have their live ranges extended to the beginning of
         * the method to account for the arg reg/memory -> global register copies
@@ -506,4 +490,64 @@ mono_analyze_liveness (MonoCompile *cfg)
                mono_bitset_print (bb->live_out_set); 
        }
 #endif
+
+       optimize_initlocals (cfg);
+}
+
+static void
+update_used (MonoCompile *cfg, MonoInst *inst, MonoBitSet *used)
+{
+       int arity = mono_burg_arity [inst->opcode];
+
+       if (arity)
+               update_used (cfg, inst->inst_i0, used);
+
+       if (arity > 1)
+               update_used (cfg, inst->inst_i1, used);
+
+       if (inst->ssa_op & MONO_SSA_LOAD_STORE) {
+               if (inst->ssa_op == MONO_SSA_LOAD) {
+                       int idx = inst->inst_i0->inst_c0;
+
+                       mono_bitset_set_fast (used, idx);
+               }
+       }
+} 
+
+/**
+ * optimize_initlocals:
+ *
+ * Try to optimize away some of the redundant initialization code inserted because of
+ * 'locals init' using the liveness information.
+ */
+static void
+optimize_initlocals (MonoCompile *cfg)
+{
+       MonoBitSet *used;
+       MonoInst *ins;
+       MonoBasicBlock *initlocals_bb;
+
+       used = mono_bitset_new (cfg->num_varinfo, 0);
+
+       mono_bitset_clear_all (used);
+       initlocals_bb = cfg->bb_entry->next_bb;
+       MONO_BB_FOR_EACH_INS (initlocals_bb, ins)
+               update_used (cfg, ins, used);
+
+       MONO_BB_FOR_EACH_INS (initlocals_bb, ins) {
+               if (ins->ssa_op == MONO_SSA_STORE) {
+                       int idx = ins->inst_i0->inst_c0;
+                       MonoInst *var = cfg->varinfo [idx];
+
+                       if (var && !mono_bitset_test_fast (used, idx) && !mono_bitset_test_fast (initlocals_bb->live_out_set, var->inst_c0) && (var != cfg->ret) && !(var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT))) {
+                               if (ins->inst_i1 && ((ins->inst_i1->opcode == OP_ICONST) || (ins->inst_i1->opcode == OP_I8CONST))) {
+                                       NULLIFY_INS (ins);
+                                       ins->ssa_op = MONO_SSA_NOP;
+                                       MONO_VARINFO (cfg, var->inst_c0)->spill_costs -= 1;                                     
+                               }
+                       }
+               }
+       }
+
+       g_free (used);
 }