X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fssa.c;h=c8718a74107be5ae0c3851646ab542a129414ebc;hb=00e065484e866f3a0349c882f804c4a79a13ee5c;hp=3c35b293e0f47c59c5619a51b698ac4601063bfc;hpb=b7c17c47e6b3c02192e64175cb5ee0ce7f7dda1b;p=mono.git diff --git a/mono/mini/ssa.c b/mono/mini/ssa.c index 3c35b293e0f..c8718a74107 100644 --- a/mono/mini/ssa.c +++ b/mono/mini/ssa.c @@ -11,8 +11,6 @@ #include "mini.h" -extern guint8 mono_burg_arity []; - #define USE_ORIGINAL_VARS #define CREATE_PRUNED_SSA @@ -32,6 +30,16 @@ extern guint8 mono_burg_arity []; } 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) { @@ -94,7 +102,7 @@ replace_usage (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, MonoInst ** 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; @@ -137,7 +145,7 @@ extends_live (MonoInst *inst) 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) { @@ -203,7 +211,7 @@ mono_ssa_rename_vars (MonoCompile *cfg, int max_vars, MonoBasicBlock *bb, MonoIn 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); @@ -266,7 +274,7 @@ mono_ssa_compute (MonoCompile *cfg) 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); @@ -328,6 +336,8 @@ mono_ssa_compute (MonoCompile *cfg) 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)); @@ -406,7 +416,7 @@ mono_ssa_replace_copies (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, c 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; @@ -517,7 +527,7 @@ mono_ssa_remove (MonoCompile *cfg) 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); } @@ -525,7 +535,7 @@ mono_ssa_remove (MonoCompile *cfg) 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); } @@ -569,16 +579,37 @@ typedef struct { MonoInst *inst; } MonoVarUsageInfo; -static void + + + +/* + * Returns TRUE if the tree can have side effects. + */ +static gboolean analyze_dev_use (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *root, MonoInst *inst) { MonoMethodVar *info; int i, idx, arity; + gboolean has_side_effects; if (!inst) - return; + return FALSE; arity = mono_burg_arity [inst->opcode]; + switch (inst->opcode) { +#define ANALYZE_DEV_USE_SPECIFIC_OPS 1 +#define OPDEF(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) case a1: +#include "simple-cee-ops.h" +#undef OPDEF +#define MINI_OP(a1,a2) case a1: +#include "simple-mini-ops.h" +#undef MINI_OP +#undef ANALYZE_DEV_USE_SPECIFIC_OPS + has_side_effects = FALSE; + break; + default: + has_side_effects = TRUE; + } if ((inst->ssa_op == MONO_SSA_STORE) && (inst->inst_i0->opcode == OP_LOCAL /*|| inst->inst_i0->opcode == OP_ARG */)) { @@ -604,12 +635,12 @@ analyze_dev_use (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *root, MonoInst //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; @@ -617,15 +648,19 @@ analyze_dev_use (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *root, MonoInst //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) - analyze_dev_use (cfg, bb, root, inst->inst_left); + if (analyze_dev_use (cfg, bb, root, inst->inst_left)) + has_side_effects = TRUE; if (arity > 1) - analyze_dev_use (cfg, bb, root, inst->inst_right); + if (analyze_dev_use (cfg, bb, root, inst->inst_right)) + has_side_effects = TRUE; } } + + return has_side_effects; } @@ -675,7 +710,6 @@ mono_ssa_avoid_copies (MonoCompile *cfg) 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; @@ -695,7 +729,11 @@ 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) { - analyze_dev_use (cfg, bb, inst, 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)) { + inst->inst_i0->flags |= MONO_INST_DEFINITION_HAS_SIDE_EFFECTS; + } } } @@ -750,13 +788,13 @@ simulate_long_compare (int opcode, gint64 a, gint64 b) 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 (); } @@ -766,7 +804,7 @@ simulate_long_compare (int opcode, gint64 a, gint64 b) #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) { \ @@ -867,7 +905,7 @@ fold_tree (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, MonoInst **carr } 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; @@ -898,7 +936,7 @@ fold_tree (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, MonoInst **carr 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]; @@ -934,8 +972,11 @@ visit_inst (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, GList **cvars, 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)) { @@ -943,7 +984,7 @@ visit_inst (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, GList **cvars, *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; @@ -952,7 +993,7 @@ visit_inst (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, GList **cvars, } } } 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; @@ -1075,7 +1116,7 @@ mono_ssa_cprop (MonoCompile *cfg) 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); @@ -1092,7 +1133,7 @@ mono_ssa_cprop (MonoCompile *cfg) 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; @@ -1125,6 +1166,7 @@ add_to_dce_worklist (MonoCompile *cfg, MonoMethodVar *var, MonoMethodVar *use, G 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; } @@ -1158,13 +1200,15 @@ mono_ssa_deadce (MonoCompile *cfg) 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_DEFINITION_HAS_SIDE_EFFECTS|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"); @@ -1180,6 +1224,7 @@ mono_ssa_deadce (MonoCompile *cfg) 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;