#include "mini.h"
#include "inssel.h"
+#include "aliasing.h"
//#define DEBUG_LIVENESS
if (arity > 1)
update_gen_kill_set (cfg, bb, inst->inst_i1, inst_num);
- if (inst->ssa_op == MONO_SSA_LOAD) {
- int idx = inst->inst_i0->inst_c0;
- MonoMethodVar *vi = MONO_VARINFO (cfg, idx);
- g_assert (idx < max_vars);
- if (bb->region != -1) {
- /*
- * Variables used in exception regions can't be allocated to
- * registers.
- */
- cfg->varinfo [vi->idx]->flags |= MONO_INST_VOLATILE;
+ if ((inst->ssa_op & MONO_SSA_LOAD_STORE) || (inst->opcode == OP_DUMMY_STORE)) {
+ MonoLocalVariableList* affected_variables;
+ MonoLocalVariableList local_affected_variable;
+
+ if (cfg->aliasing_info == NULL) {
+ if ((inst->ssa_op == MONO_SSA_LOAD) || (inst->ssa_op == MONO_SSA_STORE) || (inst->opcode == OP_DUMMY_STORE)) {
+ local_affected_variable.variable_index = inst->inst_i0->inst_c0;
+ local_affected_variable.next = NULL;
+ affected_variables = &local_affected_variable;
+ } else {
+ affected_variables = NULL;
+ }
+ } else {
+ affected_variables = mono_aliasing_get_affected_variables_for_inst_traversing_code (cfg->aliasing_info, inst);
}
- update_live_range (cfg, idx, bb->dfn, inst_num);
- if (!mono_bitset_test (bb->kill_set, idx))
- mono_bitset_set (bb->gen_set, idx);
- vi->spill_costs += 1 + (bb->nesting * 2);
- } else if (inst->ssa_op == MONO_SSA_STORE) {
- int idx = inst->inst_i0->inst_c0;
- MonoMethodVar *vi = MONO_VARINFO (cfg, idx);
- g_assert (idx < max_vars);
- g_assert (inst->inst_i1->opcode != OP_PHI);
- if (bb->region != -1) {
- /*
- * Variables used in exception regions can't be allocated to
- * registers.
- */
- cfg->varinfo [vi->idx]->flags |= MONO_INST_VOLATILE;
+
+ if (inst->ssa_op & MONO_SSA_LOAD) {
+ MonoLocalVariableList* affected_variable = affected_variables;
+ while (affected_variable != NULL) {
+ 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 (bb->kill_set, idx))
+ mono_bitset_set (bb->gen_set, idx);
+ if (inst->ssa_op == MONO_SSA_LOAD)
+ vi->spill_costs += 1 + (bb->nesting * 2);
+
+ affected_variable = affected_variable->next;
+ }
+ } else if ((inst->ssa_op == MONO_SSA_STORE) || (inst->opcode == OP_DUMMY_STORE)) {
+ MonoLocalVariableList* affected_variable = affected_variables;
+ while (affected_variable != NULL) {
+ int idx = affected_variable->variable_index;
+ MonoMethodVar *vi = MONO_VARINFO (cfg, idx);
+ 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 (bb->kill_set, idx);
+ if (inst->ssa_op == MONO_SSA_STORE)
+ vi->spill_costs += 1 + (bb->nesting * 2);
+
+ affected_variable = affected_variable->next;
+ }
+ }
+ } else if (inst->opcode == CEE_JMP) {
+ /* Keep arguments live! */
+ int i;
+ for (i = 0; i < cfg->num_varinfo; i++) {
+ if (cfg->varinfo [i]->opcode == OP_ARG) {
+ if (!mono_bitset_test (bb->kill_set, i))
+ mono_bitset_set (bb->gen_set, i);
+ }
}
- update_live_range (cfg, idx, bb->dfn, inst_num);
- mono_bitset_set (bb->kill_set, idx);
- vi->spill_costs += 1 + (bb->nesting * 2);
}
}
if (arity > 1)
update_volatile (cfg, bb, inst->inst_i1, inst_num);
- if ((inst->ssa_op == MONO_SSA_LOAD) || (inst->ssa_op == MONO_SSA_STORE)) {
- int idx = inst->inst_i0->inst_c0;
- MonoMethodVar *vi = MONO_VARINFO (cfg, idx);
- g_assert (idx < max_vars);
- cfg->varinfo [vi->idx]->flags |= MONO_INST_VOLATILE;
+ if (inst->ssa_op & MONO_SSA_LOAD_STORE) {
+ MonoLocalVariableList* affected_variables;
+ MonoLocalVariableList local_affected_variable;
+
+ if (cfg->aliasing_info == NULL) {
+ if ((inst->ssa_op == MONO_SSA_LOAD) || (inst->ssa_op == MONO_SSA_STORE)) {
+ local_affected_variable.variable_index = inst->inst_i0->inst_c0;
+ local_affected_variable.next = NULL;
+ affected_variables = &local_affected_variable;
+ } else {
+ affected_variables = NULL;
+ }
+ } else {
+ affected_variables = mono_aliasing_get_affected_variables_for_inst_traversing_code (cfg->aliasing_info, inst);
+ }
+
+ while (affected_variables != NULL) {
+ int idx = affected_variables->variable_index;
+ MonoMethodVar *vi = MONO_VARINFO (cfg, idx);
+ g_assert (idx < max_vars);
+ cfg->varinfo [vi->idx]->flags |= MONO_INST_VOLATILE;
+
+ affected_variables = affected_variables->next;
+ }
}
}
if (g_slist_find (*visited, bb))
return;
+ 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++) {
update_volatile (cfg, bb, inst, tree_num);
}
* so make them volatile. See bug #42136. This will not be neccessary when
* the back ends could guarantee that the variables will be in the
* correct registers when a handler is called.
+ * This includes try blocks too, since a variable in a try block might be
+ * accessed after an exception handler has been run.
*/
for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
- if (bb->region == -1)
+
+ if (bb->region == -1 || MONO_BBLOCK_IS_IN_REGION (bb, MONO_REGION_TRY))
continue;
visit_bb (cfg, bb, &visited);
bb->live_in_set = mono_bitset_mp_new (cfg->mempool, max_vars);
bb->live_out_set = mono_bitset_mp_new (cfg->mempool, max_vars);
}
+ for (i = 0; i < max_vars; i ++) {
+ MONO_VARINFO (cfg, i)->range.first_use.abs_pos = ~ 0;
+ MONO_VARINFO (cfg, i)->range.last_use .abs_pos = 0;
+ MONO_VARINFO (cfg, i)->spill_costs = 0;
+ }
for (i = 0; i < cfg->num_bblocks; ++i) {
MonoBasicBlock *bb = cfg->bblocks [i];
MonoInst *inst;
int tree_num;
+ 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++) {
- //mono_print_tree (inst); printf ("\n");
+#ifdef DEBUG_LIVENESS
+ mono_print_tree (inst); printf ("\n");
+#endif
update_gen_kill_set (cfg, bb, inst, tree_num);
}
}
}
+ /* 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
+ * in the prolog (bug #74992).
+ */
+
+ for (i = 0; i < max_vars; i ++) {
+ MonoMethodVar *vi = MONO_VARINFO (cfg, i);
+ if (cfg->varinfo [vi->idx]->opcode == OP_ARG)
+ vi->range.first_use.abs_pos = 0;
+ }
+
#ifdef DEBUG_LIVENESS
for (i = cfg->num_bblocks - 1; i >= 0; i--) {
MonoBasicBlock *bb = cfg->bblocks [i];
}
#endif
}
-