Branch: refs/heads/master
Home: https://github.com/mono/mono
Compare: https://github.com/mono/mono/compare/bbd3769cde29...363b1864e808
Commit: e30fed93a6945acdc2435a4f1c8153ee33296629
Author: Rodrigo Kumpera <[email protected]> (kumpera)
Date: 2013-10-31 21:37:06 GMT
URL: https://github.com/mono/mono/commit/e30fed93a6945acdc2435a4f1c8153ee33296629
[jit] Add new optimization flag for alias analysis.
Changed paths:
M mono/mini/driver.c
M mono/mini/optflags-def.h
Modified: mono/mini/driver.c
===================================================================
@@ -137,6 +137,7 @@
MONO_OPT_CMOV | \
MONO_OPT_GSHARED | \
MONO_OPT_SIMD | \
+ MONO_OPT_ALIAS_ANALYSIS | \
MONO_OPT_AOT)
#define EXCLUDED_FROM_ALL (MONO_OPT_SHARED | MONO_OPT_PRECOMP | MONO_OPT_UNSAFE | MONO_OPT_GSHAREDVT)
@@ -309,16 +310,19 @@
MONO_OPT_BRANCH,
MONO_OPT_CFOLD,
MONO_OPT_FCMOV,
+ MONO_OPT_ALIAS_ANALYSIS,
#ifdef MONO_ARCH_SIMD_INTRINSICS
MONO_OPT_SIMD,
MONO_OPT_SSE2,
MONO_OPT_SIMD | MONO_OPT_SSE2,
#endif
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_INTRINS,
+ MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_INTRINS | MONO_OPT_ALIAS_ANALYSIS,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_CFOLD,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE,
+ MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_ALIAS_ANALYSIS,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS | MONO_OPT_TAILC,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS | MONO_OPT_SSA,
Modified: mono/mini/optflags-def.h
===================================================================
@@ -26,3 +26,4 @@
OPTFLAG(GSHAREDVT,24, "gsharedvt", "Generic sharing for valuetypes")
OPTFLAG(SIMD ,26, "simd", "Simd intrinsics")
OPTFLAG(UNSAFE ,27, "unsafe", "Remove bound checks and perform other dangerous changes")
+OPTFLAG(ALIAS_ANALYSIS ,28, "alias-analysis", "Alias analysis of locals")
Commit: cdd96589ad20ccb75b46eed22a871d64d8e54e1d
Author: Rodrigo Kumpera <[email protected]> (kumpera)
Date: 2013-10-31 21:37:06 GMT
URL: https://github.com/mono/mono/commit/cdd96589ad20ccb75b46eed22a871d64d8e54e1d
[jit]Replace all usages of MONO_INST_INDIRECT to force regalloc with MONO_INST_VOLATILE.
The indirect flag should only be used to signal that the address of the given variable
has been taken. This means that it should be possible to recompute that flag from the IR.
The usage of the volatile flag remains not ideal as it conflates two separate issues
and will in the future hinder efforts to implement address based alias analysis.
Changed paths:
M mono/mini/method-to-ir.c
Modified: mono/mini/method-to-ir.c
===================================================================
@@ -608,7 +608,7 @@
var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
/* prevent it from being register allocated */
- var->flags |= MONO_INST_INDIRECT;
+ var->flags |= MONO_INST_VOLATILE;
g_hash_table_insert (cfg->spvars, GINT_TO_POINTER (region), var);
}
@@ -630,7 +630,7 @@
var = mono_compile_create_var (cfg, &mono_defaults.object_class->byval_arg, OP_LOCAL);
/* prevent it from being register allocated */
- var->flags |= MONO_INST_INDIRECT;
+ var->flags |= MONO_INST_VOLATILE;
g_hash_table_insert (cfg->exvars, GINT_TO_POINTER (offset), var);
@@ -1155,7 +1155,7 @@
if (!cfg->rgctx_var) {
cfg->rgctx_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
/* force the var to be stack allocated */
- cfg->rgctx_var->flags |= MONO_INST_INDIRECT;
+ cfg->rgctx_var->flags |= MONO_INST_VOLATILE;
}
return cfg->rgctx_var;
@@ -6845,7 +6845,7 @@ gboolean check_linkdemand (MonoCompile *cfg, MonoMethod *caller, MonoMethod *cal
var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
/* prevent it from being register allocated */
- //var->flags |= MONO_INST_INDIRECT;
+ //var->flags |= MONO_INST_VOLATILE;
cfg->gsharedvt_info_var = var;
ins = emit_get_rgctx_gsharedvt_method (cfg, mini_method_check_context_used (cfg, method), method, info);
@@ -6854,7 +6854,7 @@ gboolean check_linkdemand (MonoCompile *cfg, MonoMethod *caller, MonoMethod *cal
/* Allocate locals */
locals_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
/* prevent it from being register allocated */
- //locals_var->flags |= MONO_INST_INDIRECT;
+ //locals_var->flags |= MONO_INST_VOLATILE;
cfg->gsharedvt_locals_var = locals_var;
dreg = alloc_ireg (cfg);
@@ -6959,7 +6959,7 @@ gboolean check_linkdemand (MonoCompile *cfg, MonoMethod *caller, MonoMethod *cal
/* FIXME: Is there a better way to do this?
We need the variable live for the duration
of the whole method. */
- cfg->args [0]->flags |= MONO_INST_INDIRECT;
+ cfg->args [0]->flags |= MONO_INST_VOLATILE;
}
}
@@ -11159,7 +11159,7 @@ gboolean check_linkdemand (MonoCompile *cfg, MonoMethod *caller, MonoMethod *cal
if (!cfg->dyn_call_var) {
cfg->dyn_call_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
/* prevent it from being register allocated */
- cfg->dyn_call_var->flags |= MONO_INST_INDIRECT;
+ cfg->dyn_call_var->flags |= MONO_INST_VOLATILE;
}
/* Has to use a call inst since it local regalloc expects it */
Commit: 8c92a0da08f0768f7c1b23e3dfced9e30df63fff
Author: Rodrigo Kumpera <[email protected]> (kumpera)
Date: 2013-10-31 21:37:06 GMT
URL: https://github.com/mono/mono/commit/8c92a0da08f0768f7c1b23e3dfced9e30df63fff
[jit] Introduce has_indirection flag in MonoCompile to signal that LDADDR was generated.
To reduce the cost of alias analysis we detect which methods can potentially profit from
the optimization.
The current detection logic is very simple, every time LDADDR is generated, we set
has_indirection to TRUE.
Changed paths:
M mono/mini/ir-emit.h
M mono/mini/mini-amd64.c
M mono/mini/mini.h
Modified: mono/mini/ir-emit.h
===================================================================
@@ -337,6 +337,7 @@
(dest)->type = STACK_MP; \
(dest)->klass = (var)->klass; \
(dest)->dreg = alloc_dreg ((cfg), STACK_MP); \
+ (cfg)->has_indirection = TRUE; \
if (G_UNLIKELY (cfg->gsharedvt) && mini_is_gsharedvt_variable_type ((cfg), (var)->inst_vtype)) { handle_gsharedvt_ldaddr ((cfg)); } \
if (SIZEOF_REGISTER == 4 && DECOMPOSE_INTO_REGPAIR ((var)->type)) { MonoInst *var1 = get_vreg_to_inst (cfg, (var)->dreg + 1); MonoInst *var2 = get_vreg_to_inst (cfg, (var)->dreg + 2); g_assert (var1); g_assert (var2); var1->flags |= MONO_INST_INDIRECT; var2->flags |= MONO_INST_INDIRECT; } \
} while (0)
Modified: mono/mini/mini-amd64.c
===================================================================
@@ -2494,6 +2494,7 @@
g_assert (!cfg->arch.no_pushes);
MONO_INST_NEW (cfg, load, OP_LDADDR);
+ cfg->has_indirection = TRUE;
load->inst_p0 = vtaddr;
vtaddr->flags |= MONO_INST_INDIRECT;
load->type = STACK_MP;
Modified: mono/mini/mini.h
===================================================================
@@ -1455,6 +1455,7 @@ enum {
guint compute_gc_maps : 1;
guint soft_breakpoints : 1;
guint arch_eh_jit_info : 1;
+ guint has_indirection : 1;
gpointer debug_info;
guint32 lmf_offset;
guint16 *intvars;
Commit: 33e4ab9bde580b0db5699bc9d08cc6649f0c9583
Author: Rodrigo Kumpera <[email protected]> (kumpera)
Date: 2013-10-31 21:37:07 GMT
URL: https://github.com/mono/mono/commit/33e4ab9bde580b0db5699bc9d08cc6649f0c9583
[jit] Add counters for alias analysis.
Changed paths:
M mono/mini/mini.c
M mono/mini/mini.h
Modified: mono/mini/mini.c
===================================================================
@@ -6922,6 +6922,10 @@ void *mono_global_codeman_reserve (int size)
mono_counters_register ("Method cache lookups", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_lookups);
mono_counters_register ("Compiled CIL code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.cil_code_size);
mono_counters_register ("Native code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.native_code_size);
+ mono_counters_register ("Aliases found", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.alias_found);
+ mono_counters_register ("Aliases eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.alias_removed);
+ mono_counters_register ("Aliased loads eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.loads_eliminated);
+ mono_counters_register ("Aliased stores eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.stores_eliminated);
}
static void runtime_invoke_info_free (gpointer value);
Modified: mono/mini/mini.h
===================================================================
@@ -1625,6 +1625,10 @@ enum {
gint32 cas_linkdemand;
gint32 cas_demand_generation;
gint32 generic_virtual_invocations;
+ gint32 alias_found;
+ gint32 alias_removed;
+ gint32 loads_eliminated;
+ gint32 stores_eliminated;
int methods_with_llvm;
int methods_without_llvm;
char *max_ratio_method;
Commit: 363b1864e808fa34510738fd3ae39bbe98a01e99
Author: Rodrigo Kumpera <[email protected]> (kumpera)
Date: 2013-10-31 21:37:13 GMT
URL: https://github.com/mono/mono/commit/363b1864e808fa34510738fd3ae39bbe98a01e99
[jit]Add an alias analysis pass to the JIT.
The alias analysis pass is capable of simplifying indirection against
local or temporary variables. It will replace a memory load or store
with direct access to the variable.
It does a local pass looking for addresses and replacing memory
ops with direct ops.
If any conversion happens, it does a DCE pass to try to kill those
LDADDR and then recalculate the indirect flag.
Finally, if the number of indirect variables is reduced, it does a
global to local vreg pass and another DCE pass to kill most spurious
copying.
Performance numbers on 32bits OSX:
Code size:
mcs: -11.366 (0.6%)
corlib: -15.397 (0.6%)
Execution time increased by less than 0.2% which is about the same
value of the test variance.
Numbers are not impressive since we don't perform store forwarding
or constant load elimination. Proper handling of value type aggregates
and longs would move us much further.
Changed paths:
M mono/mini/Makefile.am.in
M mono/mini/mini.c
M mono/mini/mini.h
Added paths:
A mono/mini/alias-analysis.c
Modified: mono/mini/Makefile.am.in
===================================================================
@@ -421,7 +421,8 @@ common_sources = \
debug-debugger.h \
xdebug.c \
mini-llvm.h \
- mini-llvm-cpp.h
+ mini-llvm-cpp.h \
+ alias-analysis.c
test_sources = \
basic-calls.cs \
Added: mono/mini/alias-analysis.c
===================================================================
@@ -0,0 +1,333 @@
+/*
+ * alias-analysis.c: Implement simple alias analysis for local variables.
+ *
+ * Author:
+ * Rodrigo Kumpera ([email protected])
+ *
+ * (C) 2013 Xamarin
+ */
+
+#include <config.h>
+#include <stdio.h>
+
+#include "mini.h"
+#include "ir-emit.h"
+#include "glib.h"
+
+static gboolean
+is_int_stack_size (int type)
+{
+#if SIZEOF_VOID_P == 4
+ return type == STACK_I4 || type == STACK_MP;
+#else
+ return type == STACK_I4;
+#endif
+}
+
+static gboolean
+is_long_stack_size (int type)
+{
+#if SIZEOF_VOID_P == 8
+ return type == STACK_I8 || type == STACK_MP;
+#else
+ return type == STACK_I8;
+#endif
+}
+
+
+static gboolean
+lower_load (MonoCompile *cfg, MonoInst *load, MonoInst *ldaddr)
+{
+ MonoInst *var = ldaddr->inst_p0;
+ MonoType *type = &var->klass->byval_arg;
+ int replaced_op = mono_type_to_load_membase (cfg, type);
+
+ if (load->opcode == OP_LOADV_MEMBASE && load->klass != var->klass) {
+ if (cfg->verbose_level > 2)
+ printf ("Incompatible load_vtype classes %s x %s\n", load->klass->name, var->klass->name);
+ return FALSE;
+ }
+
+ if (replaced_op != load->opcode) {
+ if (cfg->verbose_level > 2)
+ printf ("Incompatible load type: expected %s but got %s\n",
+ mono_inst_name (replaced_op),
+ mono_inst_name (load->opcode));
+ return FALSE;
+ } else {
+ if (cfg->verbose_level > 2) { printf ("mem2reg replacing: "); mono_print_ins (load); }
+ }
+
+ load->opcode = mono_type_to_regmove (cfg, type);
+ type_to_eval_stack_type (cfg, type, load);
+ load->sreg1 = var->dreg;
+ mono_jit_stats.loads_eliminated++;
+ return TRUE;
+}
+
+static gboolean
+lower_store (MonoCompile *cfg, MonoInst *store, MonoInst *ldaddr)
+{
+ MonoInst *var = ldaddr->inst_p0;
+ MonoType *type = &var->klass->byval_arg;
+ int replaced_op = mono_type_to_store_membase (cfg, type);
+
+ if (store->opcode == OP_STOREV_MEMBASE && store->klass != var->klass) {
+ if (cfg->verbose_level > 2)
+ printf ("Incompatible store_vtype classes %s x %s\n", store->klass->name, store->klass->name);
+ return FALSE;
+ }
+
+
+ if (replaced_op != store->opcode) {
+ if (cfg->verbose_level > 2)
+ printf ("Incompatible store_reg type: expected %s but got %s\n",
+ mono_inst_name (replaced_op),
+ mono_inst_name (store->opcode));
+ return FALSE;
+ } else {
+ if (cfg->verbose_level > 2) { printf ("mem2reg replacing: "); mono_print_ins (store); }
+ }
+
+ store->opcode = mono_type_to_regmove (cfg, type);
+ type_to_eval_stack_type (cfg, type, store);
+ store->dreg = var->dreg;
+ mono_jit_stats.stores_eliminated++;
+ return TRUE;
+}
+
+static gboolean
+lower_store_imm (MonoCompile *cfg, MonoInst *store, MonoInst *ldaddr)
+{
+ MonoInst *var = 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)
+ return FALSE;
+
+ switch (store->opcode) {
+#if SIZEOF_VOID_P == 4
+ case OP_STORE_MEMBASE_IMM:
+#endif
+ case OP_STOREI4_MEMBASE_IMM:
+ if (!is_int_stack_size (var->type)) {
+ if (cfg->verbose_level > 2) printf ("Incompatible variable of size != 4\n");
+ return FALSE;
+ }
+ if (cfg->verbose_level > 2) { printf ("mem2reg replacing: "); mono_print_ins (store); }
+ store->opcode = OP_ICONST;
+ store->type = STACK_I4;
+ store->dreg = var->dreg;
+ store->inst_c0 = store->inst_imm;
+ break;
+
+#if SIZEOF_VOID_P == 8
+ case OP_STORE_MEMBASE_IMM:
+#endif
+ case OP_STOREI8_MEMBASE_IMM:
+ if (!is_long_stack_size (var->type)) {
+ if (cfg->verbose_level > 2) printf ("Incompatible variable of size != 8\n");
+ return FALSE;
+ }
+ if (cfg->verbose_level > 2) { printf ("mem2reg replacing: "); mono_print_ins (store); }
+ store->opcode = OP_I8CONST;
+ store->type = STACK_I8;
+ store->dreg = var->dreg;
+ store->inst_l = store->inst_imm;
+ break;
+ default:
+ return FALSE;
+ }
+ mono_jit_stats.stores_eliminated++;
+ return TRUE;
+}
+
+static gboolean
+lower_memory_access (MonoCompile *cfg)
+{
+ MonoBasicBlock *bb;
+ MonoInst *ins, *tmp;
+ gboolean needs_dce = FALSE;
+ GHashTable *addr_loads = g_hash_table_new (NULL, NULL);
+ //FIXME optimize
+ for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
+ g_hash_table_remove_all (addr_loads);
+
+ for (ins = bb->code; ins; ins = ins->next) {
+ switch (ins->opcode) {
+ case OP_LDADDR:
+ g_hash_table_insert (addr_loads, GINT_TO_POINTER (ins->dreg), ins);
+ if (cfg->verbose_level > 2) { printf ("New address: "); mono_print_ins (ins); }
+ break;
+ case OP_MOVE:
+ tmp = (MonoInst*)g_hash_table_lookup (addr_loads, GINT_TO_POINTER (ins->sreg1));
+ /*
+ Forward propagate known aliases
+ ldaddr R10 <- R8
+ mov R11 <- R10
+ */
+ if (tmp) {
+ g_hash_table_insert (addr_loads, GINT_TO_POINTER (ins->dreg), tmp);
+ if (cfg->verbose_level > 2) { printf ("New alias: "); mono_print_ins (ins); }
+ } else {
+ /*
+ Source value is not a know address, kill the variable.
+ */
+ if (g_hash_table_remove (addr_loads, GINT_TO_POINTER (ins->dreg))) {
+ if (cfg->verbose_level > 2) { printf ("Killed alias: "); mono_print_ins (ins); }
+ }
+ }
+ break;
+
+ case OP_LOADV_MEMBASE:
+ case OP_LOAD_MEMBASE:
+ case OP_LOADU1_MEMBASE:
+ case OP_LOADI2_MEMBASE:
+ case OP_LOADU2_MEMBASE:
+ case OP_LOADI4_MEMBASE:
+ case OP_LOADU4_MEMBASE:
+ case OP_LOADI1_MEMBASE:
+ case OP_LOADI8_MEMBASE:
+ case OP_LOADR4_MEMBASE:
+ case OP_LOADR8_MEMBASE:
+ if (ins->inst_offset != 0)
+ continue;
+ tmp = 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);
+ }
+ break;
+
+ case OP_STORE_MEMBASE_REG:
+ case OP_STOREI1_MEMBASE_REG:
+ case OP_STOREI2_MEMBASE_REG:
+ case OP_STOREI4_MEMBASE_REG:
+ case OP_STOREI8_MEMBASE_REG:
+ case OP_STORER4_MEMBASE_REG:
+ case OP_STORER8_MEMBASE_REG:
+ case OP_STOREV_MEMBASE:
+ if (ins->inst_offset != 0)
+ continue;
+ tmp = 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);
+ }
+ break;
+
+ case OP_STORE_MEMBASE_IMM:
+ case OP_STOREI4_MEMBASE_IMM:
+ case OP_STOREI8_MEMBASE_IMM:
+ if (ins->inst_offset != 0)
+ continue;
+ tmp = 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;
+ }
+ }
+ }
+ g_hash_table_destroy (addr_loads);
+ return needs_dce;
+}
+
+static gboolean
+recompute_aliased_variables (MonoCompile *cfg)
+{
+ int i;
+ MonoBasicBlock *bb;
+ MonoInst *ins;
+ int kills = 0;
+ int adds = 0;
+
+ for (i = 0; i < cfg->num_varinfo; i++) {
+ MonoInst *var = cfg->varinfo [i];
+ if (var->flags & MONO_INST_INDIRECT) {
+ if (cfg->verbose_level > 2) {
+ printf ("Killing :"); mono_print_ins (var);
+ }
+ ++kills;
+ }
+ var->flags &= ~MONO_INST_INDIRECT;
+ }
+
+ if (!kills)
+ return FALSE;
+
+ for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
+ for (ins = bb->code; ins; ins = ins->next) {
+ if (ins->opcode == OP_LDADDR) {
+ if (cfg->verbose_level > 2) { printf ("Found op :"); mono_print_ins (ins); }
+
+ MonoInst *var = (MonoInst*)ins->inst_p0;
+ if (!(var->flags & MONO_INST_INDIRECT)) {
+ if (cfg->verbose_level) { printf ("Restoring :"); mono_print_ins (var); }
+ ++adds;
+ }
+ var->flags |= MONO_INST_INDIRECT;
+ }
+ }
+ }
+
+ mono_jit_stats.alias_found += kills;
+ mono_jit_stats.alias_removed += kills - adds;
+ if (kills > adds) {
+ if (cfg->verbose_level > 2) {
+ printf ("Method: %s\n", mono_method_full_name (cfg->method, 1));
+ printf ("Kills %d Adds %d\n", kills, adds);
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+FIXME:
+ Don't DCE on the whole CFG, only the BBs that have changed.
+
+TODO:
+ SRVT of small types can fix cases of mismatch for fields of a different type than the component.
+ Handle aliasing of byrefs in call conventions.
+*/
+void
+mono_local_alias_analysis (MonoCompile *cfg)
+{
+ if (!cfg->has_indirection)
+ return;
+
+ if (cfg->verbose_level > 2)
+ mono_print_code (cfg, "BEFORE ALIAS_ANALYSIS");
+
+ /*
+ Remove indirection and memory access of known variables.
+ */
+ if (!lower_memory_access (cfg))
+ goto done;
+
+ /*
+ By replacing indirect access with direct operations, some LDADDR ops become dead. Kill them.
+ */
+ if (cfg->opt & MONO_OPT_DEADCE)
+ mono_local_deadce (cfg);
+
+ /*
+ Some variables no longer need to be flagged as indirect, find them.
+ */
+ 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);
+
+done:
+ if (cfg->verbose_level > 2)
+ mono_print_code (cfg, "AFTER ALIAS_ANALYSIS");
+}
Modified: mono/mini/mini.c
===================================================================
@@ -5211,6 +5211,8 @@ void *mono_global_codeman_reserve (int size)
mono_handle_global_vregs (cfg);
if (cfg->opt & MONO_OPT_DEADCE)
mono_local_deadce (cfg);
+ if (cfg->opt & MONO_OPT_ALIAS_ANALYSIS)
+ mono_local_alias_analysis (cfg);
/* Disable this for LLVM to make the IR easier to handle */
if (!COMPILE_LLVM (cfg))
mono_if_conversion (cfg);
Modified: mono/mini/mini.h
===================================================================
@@ -2518,6 +2518,8 @@ void mono_debug_add_aot_method (MonoDomain *domain,
mono_local_cprop (MonoCompile *cfg);
extern void
mono_local_deadce (MonoCompile *cfg);
+void
+mono_local_alias_analysis (MonoCompile *cfg) MONO_INTERNAL;
/* CAS - stack walk */
MonoSecurityFrame* ves_icall_System_Security_SecurityFrame_GetSecurityFrame (gint32 skip) MONO_INTERNAL;
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.