} while (0)
+static GList*
+g_list_prepend_mempool (GList* l, MonoMemPool* mp, gpointer datum)
+{
+ GList* n = mono_mempool_alloc (mp, sizeof (GList));
+ n->next = l;
+ n->prev = NULL;
+ n->data = datum;
+ return n;
+}
+
static void
unlink_target (MonoBasicBlock *bb, MonoBasicBlock *target)
{
arity = mono_burg_arity [inst->opcode];
- if ((inst->ssa_op == MONO_SSA_LOAD || inst->ssa_op == MONO_SSA_MAYBE_LOAD) &&
+ if ((inst->ssa_op == MONO_SSA_LOAD || inst->ssa_op == MONO_SSA_ADDRESS_TAKEN) &&
(inst->inst_i0->opcode == OP_LOCAL || inst->inst_i0->opcode == OP_ARG)) {
MonoInst *new_var;
int idx = inst->inst_i0->inst_c0;
arity = mono_burg_arity [inst->opcode];
if (inst->ssa_op == MONO_SSA_LOAD &&
- (inst->inst_i0->opcode == OP_LOCAL /*|| inst->inst_i0->opcode == OP_ARG*/)) {
+ (inst->inst_i0->opcode == OP_LOCAL || inst->inst_i0->opcode == OP_ARG)) {
return 1;
} else {
if (arity) {
idx = inst->inst_i0->inst_c0;
g_assert (idx < max_vars);
- if (!stack [idx] && bb == cfg->bb_init) {
+ if ((!stack [idx]) && (bb == cfg->bb_init) && (inst->inst_i0->opcode != OP_ARG)) {
new_var = cfg->varinfo [idx];
} else {
new_var = mono_compile_create_var (cfg, inst->inst_i0->inst_vtype, inst->inst_i0->opcode);
g_assert (!(cfg->comp_done & MONO_COMP_SSA));
/* we dont support methods containing exception clauses */
- g_assert (((MonoMethodNormal *)cfg->method)->header->num_clauses == 0);
+ g_assert (mono_method_get_header (cfg->method)->num_clauses == 0);
g_assert (!cfg->disable_ssa);
//printf ("COMPUTS SSA %s %d\n", mono_method_full_name (cfg->method, TRUE), cfg->num_varinfo);
store->next = bb->code;
bb->code = store;
+ if (!bb->last_ins)
+ bb->last_ins = bb->code;
#ifdef DEBUG_SSA
printf ("ADD PHI BB%d %s\n", cfg->bblocks [idx]->block_num, mono_method_full_name (cfg->method, TRUE));
arity = mono_burg_arity [inst->opcode];
- if ((inst->ssa_op == MONO_SSA_LOAD || inst->ssa_op == MONO_SSA_MAYBE_LOAD || inst->ssa_op == MONO_SSA_STORE) &&
+ if ((inst->ssa_op == MONO_SSA_LOAD || inst->ssa_op == MONO_SSA_ADDRESS_TAKEN || inst->ssa_op == MONO_SSA_STORE) &&
(inst->inst_i0->opcode == OP_LOCAL || inst->inst_i0->opcode == OP_ARG)) {
MonoInst *new_var;
int idx = inst->inst_i0->inst_c0;
if (amv->range.last_use.abs_pos >= vmv->range.first_use.abs_pos)
break;
- active = g_list_remove_link (active, active);
+ active = g_list_delete_link (active, active);
regs = g_list_prepend (regs, (gpointer)amv->reg);
}
regs = g_list_prepend (regs, (gpointer)vmv->idx);
vmv->reg = (int)regs->data;
- regs = g_list_remove_link (regs, regs);
+ regs = g_list_delete_link (regs, regs);
active = mono_varlist_insert_sorted (cfg, active, vmv, TRUE);
}
//printf ("FOUND %d\n", idx);
ui->bb = bb;
ui->inst = root;
- info->uses = g_list_prepend (info->uses, ui);
+ info->uses = g_list_prepend_mempool (info->uses, cfg->mempool, ui);
}
}
}
- if ((inst->ssa_op == MONO_SSA_LOAD || inst->ssa_op == MONO_SSA_MAYBE_LOAD) &&
+ if ((inst->ssa_op == MONO_SSA_LOAD || inst->ssa_op == MONO_SSA_ADDRESS_TAKEN) &&
(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;
//printf ("FOUND %d\n", idx);
ui->bb = bb;
ui->inst = root;
- info->uses = g_list_prepend (info->uses, ui);
+ info->uses = g_list_prepend_mempool (info->uses, cfg->mempool, ui);
} else {
if (arity) {
//if (inst->ssa_op != MONO_SSA_STORE)
inst->inst_i0 = next->inst_i0;
i2->def = inst;
i1->def = NULL;
- g_list_free (i1->uses);
i1->uses = NULL;
next->opcode = CEE_NOP;
next->ssa_op = MONO_SSA_NOP;
case CEE_BNE_UN:
return a != b;
case CEE_BGE_UN:
- return (unsigned)a >= (unsigned)b;
+ return (guint64)a >= (guint64)b;
case CEE_BGT_UN:
- return (unsigned)a > (unsigned)b;
+ return (guint64)a > (guint64)b;
case CEE_BLE_UN:
- return (unsigned)a <= (unsigned)b;
+ return (guint64)a <= (guint64)b;
case CEE_BLT_UN:
- return (unsigned)a < (unsigned)b;
+ return (guint64)a < (guint64)b;
default:
g_assert_not_reached ();
}
#define EVAL_CXX(name,op,cast) \
case name: \
- if (inst->inst_i0->opcode == OP_COMPARE) { \
+ if ((inst->inst_i0->opcode == OP_COMPARE) || (inst->inst_i0->opcode == OP_LCOMPARE)) { \
r1 = evaluate_const_tree (cfg, inst->inst_i0->inst_i0, &a, carray); \
r2 = evaluate_const_tree (cfg, inst->inst_i0->inst_i1, &b, carray); \
if (r1 == 1 && r2 == 1) { \
}
if ((inst->opcode >= CEE_BEQ && inst->opcode <= CEE_BLT_UN) &&
- inst->inst_i0->opcode == OP_COMPARE) {
+ ((inst->inst_i0->opcode == OP_COMPARE) || (inst->inst_i0->opcode == OP_LCOMPARE))) {
MonoInst *v0 = inst->inst_i0->inst_i0;
MonoInst *v1 = inst->inst_i0->inst_i1;
MonoBasicBlock *target = NULL;
inst->opcode = CEE_BR;
inst->inst_target_bb = target;
}
- } else if (inst->opcode == CEE_SWITCH && evaluate_const_tree (cfg, inst->inst_left, &a, carray) == 1) {
+ } else if (inst->opcode == CEE_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];
if (inst->opcode == CEE_SWITCH) {
int r1, i, a;
+ int cases = GPOINTER_TO_INT (inst->klass);
r1 = evaluate_const_tree (cfg, inst->inst_left, &a, carray);
+ if ((r1 == 1) && ((a < 0) || (a >= cases)))
+ r1 = 2;
if (r1 == 1) {
MonoBasicBlock *tb = inst->inst_many_bb [a];
if (!(tb->flags & BB_REACHABLE)) {
*bblist = g_list_prepend (*bblist, tb);
}
} else if (r1 == 2) {
- for (i = (int)inst->klass; i >= 0; i--) {
+ for (i = GPOINTER_TO_INT (inst->klass); i >= 0; i--) {
MonoBasicBlock *tb = inst->inst_many_bb [i];
if (!(tb->flags & BB_REACHABLE)) {
tb->flags |= BB_REACHABLE;
}
}
} else if ((inst->opcode >= CEE_BEQ && inst->opcode <= CEE_BLT_UN) &&
- inst->inst_i0->opcode == OP_COMPARE) {
+ ((inst->inst_i0->opcode == OP_COMPARE) || (inst->inst_i0->opcode == OP_LCOMPARE))) {
int a, b, r1, r2;
MonoInst *v0 = inst->inst_i0->inst_i0;
MonoInst *v1 = inst->inst_i0->inst_i1;
bb = (MonoBasicBlock *)bblock_list->data;
- bblock_list = g_list_remove_link (bblock_list, bblock_list);
+ bblock_list = g_list_delete_link (bblock_list, bblock_list);
g_assert (bb->flags & BB_REACHABLE);
while (cvars) {
MonoMethodVar *info = (MonoMethodVar *)cvars->data;
- cvars = g_list_remove_link (cvars, cvars);
+ cvars = g_list_delete_link (cvars, cvars);
for (tmp = info->uses; tmp; tmp = tmp->next) {
MonoVarUsageInfo *ui = (MonoVarUsageInfo *)tmp->data;
for (tmp = use->uses; tmp; tmp = tmp->next) {
MonoVarUsageInfo *ui = (MonoVarUsageInfo *)tmp->data;
if (ui->inst == var->def) {
+ /* from the mempool */
use->uses = g_list_remove_link (use->uses, tmp);
break;
}
for (i = 0; i < cfg->num_varinfo; i++) {
MonoMethodVar *info = cfg->vars [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");
}
while (work_list) {
MonoMethodVar *info = (MonoMethodVar *)work_list->data;
- work_list = g_list_remove_link (work_list, work_list);
+ work_list = g_list_delete_link (work_list, work_list);
- if (!info->uses && info->def) {
+ if (!info->uses && info->def && (!(cfg->varinfo [info->idx]->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)))) {
MonoInst *i1;
//printf ("ELIMINATE %s: ", mono_method_full_name (cfg->method, TRUE)); mono_print_tree (info->def); printf ("\n");
MonoMethodVar *u = cfg->vars [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->ssa_op = MONO_SSA_NOP;