Build mono runtime under none desktop Windows API family, adjustments and cleanup.
[mono.git] / mono / mini / alias-analysis.c
index bc5bd8e01265cbb84d5cd94f0ccf07837590c144..c419dfa2b42abf4139037e97340225628b8670b3 100644 (file)
@@ -13,6 +13,7 @@
 #include "mini.h"
 #include "ir-emit.h"
 #include "glib.h"
+#include <mono/utils/mono-compiler.h>
 
 #ifndef DISABLE_JIT
 
@@ -40,7 +41,7 @@ is_long_stack_size (int type)
 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);
 
@@ -70,7 +71,7 @@ lower_load (MonoCompile *cfg, MonoInst *load, MonoInst *ldaddr)
 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);
 
@@ -101,7 +102,7 @@ lower_store (MonoCompile *cfg, MonoInst *store, MonoInst *ldaddr)
 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)
@@ -156,6 +157,7 @@ lower_memory_access (MonoCompile *cfg)
                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);
@@ -190,14 +192,20 @@ lower_memory_access (MonoCompile *cfg)
                        case OP_LOADU4_MEMBASE:
                        case OP_LOADI1_MEMBASE:
                        case OP_LOADI8_MEMBASE:
+#ifndef MONO_ARCH_SOFT_FLOAT_FALLBACK
                        case OP_LOADR4_MEMBASE:
+#endif
                        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;
 
@@ -206,29 +214,44 @@ lower_memory_access (MonoCompile *cfg)
                        case OP_STOREI2_MEMBASE_REG:
                        case OP_STOREI4_MEMBASE_REG:
                        case OP_STOREI8_MEMBASE_REG:
+#ifndef MONO_ARCH_SOFT_FLOAT_FALLBACK
                        case OP_STORER4_MEMBASE_REG:
+#endif
                        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));
+                               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;
-
+                       //FIXME missing storei1_membase_imm and storei2_membase_imm
                        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));
+                               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;
                        }
                }
        }
@@ -237,13 +260,14 @@ lower_memory_access (MonoCompile *cfg)
 }
 
 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];
@@ -275,7 +299,8 @@ recompute_aliased_variables (MonoCompile *cfg)
                        }
                }
        }
-       
+       *restored_vars = adds;
+
        mono_jit_stats.alias_found += kills;
        mono_jit_stats.alias_removed += kills - adds;
        if (kills > adds) {
@@ -299,6 +324,7 @@ TODO:
 void
 mono_local_alias_analysis (MonoCompile *cfg)
 {
+       int i, restored_vars = 1;
        if (!cfg->has_indirection)
                return;
 
@@ -319,21 +345,26 @@ mono_local_alias_analysis (MonoCompile *cfg)
 
        /*
        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)
                mono_print_code (cfg, "AFTER ALIAS_ANALYSIS");
 }
 
+#else /* !DISABLE_JIT */
+
+MONO_EMPTY_SOURCE_FILE (alias_analysis);
+
 #endif /* !DISABLE_JIT */