static gboolean
lower_load (MonoCompile *cfg, MonoInst *load, MonoInst *ldaddr)
{
- MonoInst *var = ldaddr->inst_p0;
+ MonoInst *var = (MonoInst *)ldaddr->inst_p0;
MonoType *type = &var->klass->byval_arg;
int replaced_op = mono_type_to_load_membase (cfg, type);
static gboolean
lower_store (MonoCompile *cfg, MonoInst *store, MonoInst *ldaddr)
{
- MonoInst *var = ldaddr->inst_p0;
+ MonoInst *var = (MonoInst *)ldaddr->inst_p0;
MonoType *type = &var->klass->byval_arg;
int replaced_op = mono_type_to_store_membase (cfg, type);
static gboolean
lower_store_imm (MonoCompile *cfg, MonoInst *store, MonoInst *ldaddr)
{
- MonoInst *var = ldaddr->inst_p0;
+ MonoInst *var = (MonoInst *)ldaddr->inst_p0;
MonoType *type = &var->klass->byval_arg;
int store_op = mono_type_to_store_membase (cfg, type);
if (store_op == OP_STOREV_MEMBASE || store_op == OP_STOREX_MEMBASE)
g_hash_table_remove_all (addr_loads);
for (ins = bb->code; ins; ins = ins->next) {
+handle_instruction:
switch (ins->opcode) {
case OP_LDADDR:
g_hash_table_insert (addr_loads, GINT_TO_POINTER (ins->dreg), ins);
case OP_LOADR8_MEMBASE:
if (ins->inst_offset != 0)
continue;
- tmp = g_hash_table_lookup (addr_loads, GINT_TO_POINTER (ins->sreg1));
+ tmp = (MonoInst *)g_hash_table_lookup (addr_loads, GINT_TO_POINTER (ins->sreg1));
if (tmp) {
if (cfg->verbose_level > 2) { printf ("Found candidate load:"); mono_print_ins (ins); }
- needs_dce |= lower_load (cfg, ins, tmp);
+ if (lower_load (cfg, ins, tmp)) {
+ needs_dce = TRUE;
+ /* Try to propagate known aliases if an OP_MOVE was inserted */
+ goto handle_instruction;
+ }
}
break;
case OP_STOREV_MEMBASE:
if (ins->inst_offset != 0)
continue;
- tmp = g_hash_table_lookup (addr_loads, GINT_TO_POINTER (ins->dreg));
+ tmp = (MonoInst *)g_hash_table_lookup (addr_loads, GINT_TO_POINTER (ins->dreg));
if (tmp) {
if (cfg->verbose_level > 2) { printf ("Found candidate store:"); mono_print_ins (ins); }
- needs_dce |= lower_store (cfg, ins, tmp);
+ if (lower_store (cfg, ins, tmp)) {
+ needs_dce = TRUE;
+ /* Try to propagate known aliases if an OP_MOVE was inserted */
+ goto handle_instruction;
+ }
}
break;
case OP_STOREI8_MEMBASE_IMM:
if (ins->inst_offset != 0)
continue;
- tmp = g_hash_table_lookup (addr_loads, GINT_TO_POINTER (ins->dreg));
+ tmp = (MonoInst *)g_hash_table_lookup (addr_loads, GINT_TO_POINTER (ins->dreg));
if (tmp) {
if (cfg->verbose_level > 2) { printf ("Found candidate store-imm:"); mono_print_ins (ins); }
needs_dce |= lower_store_imm (cfg, ins, tmp);
}
break;
+ case OP_CHECK_THIS:
+ case OP_NOT_NULL:
+ tmp = (MonoInst *)g_hash_table_lookup (addr_loads, GINT_TO_POINTER (ins->sreg1));
+ if (tmp) {
+ if (cfg->verbose_level > 2) { printf ("Found null check over local: "); mono_print_ins (ins); }
+ NULLIFY_INS (ins);
+ needs_dce = TRUE;
+ }
+ break;
}
}
}
}
static gboolean
-recompute_aliased_variables (MonoCompile *cfg)
+recompute_aliased_variables (MonoCompile *cfg, int *restored_vars)
{
int i;
MonoBasicBlock *bb;
MonoInst *ins;
int kills = 0;
int adds = 0;
+ *restored_vars = 0;
for (i = 0; i < cfg->num_varinfo; i++) {
MonoInst *var = cfg->varinfo [i];
var = (MonoInst*)ins->inst_p0;
if (!(var->flags & MONO_INST_INDIRECT)) {
- if (cfg->verbose_level) { printf ("Restoring :"); mono_print_ins (var); }
+ if (cfg->verbose_level > 1) { printf ("Restoring :"); mono_print_ins (var); }
++adds;
}
var->flags |= MONO_INST_INDIRECT;
}
}
}
-
+ *restored_vars = adds;
+
mono_jit_stats.alias_found += kills;
mono_jit_stats.alias_removed += kills - adds;
if (kills > adds) {
void
mono_local_alias_analysis (MonoCompile *cfg)
{
+ int i, restored_vars = 1;
if (!cfg->has_indirection)
return;
/*
Some variables no longer need to be flagged as indirect, find them.
+ Since indirect vars are converted into global vregs, each pass eliminates only one level of indirection.
+ Most cases only need one pass and some 2.
*/
- if (!recompute_aliased_variables (cfg))
- goto done;
-
- /*
- A lot of simplification just took place, we recompute local variables and do DCE to
- really profit from the previous gains
- */
- mono_handle_global_vregs (cfg);
- if (cfg->opt & MONO_OPT_DEADCE)
- mono_local_deadce (cfg);
+ for (i = 0; i < 3 && restored_vars > 0 && recompute_aliased_variables (cfg, &restored_vars); ++i) {
+ /*
+ A lot of simplification just took place, we recompute local variables and do DCE to
+ really profit from the previous gains
+ */
+ mono_handle_global_vregs (cfg);
+ if (cfg->opt & MONO_OPT_DEADCE)
+ mono_local_deadce (cfg);
+ }
done:
if (cfg->verbose_level > 2)