2008-02-14 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / aliasing.c
index edd0e4d66855cdcd4c3cda0522043c097f4e6981..b30e21cbcefbb4ea979c354bc5af047fa4a8724d 100644 (file)
@@ -15,8 +15,6 @@
 
 #include "aliasing.h"
 
-extern guint8 mono_burg_arity [];
-
 #define MONO_APPLY_DEADCE_TO_SINGLE_METHOD 0
 #define DEBUG_DEADCE 0
 
@@ -50,12 +48,23 @@ static const char *mono_stack_type_names[] = {
 
 
 #define OP_IS_OUTARG(op) (((op)==OP_OUTARG)||((op)==OP_OUTARG_REG)||((op)==OP_OUTARG_IMM)||((op)==OP_OUTARG_R4)||((op)==OP_OUTARG_R8)||((op)==OP_OUTARG_VT))
-#define OP_IS_CALL(op) (((op)==CEE_CALLI)||((op)==CEE_CALL)||((op)==CEE_CALLVIRT)||(((op)>=OP_VOIDCALL)&&((op)<=OP_CALL_MEMBASE)))
+#define OP_IS_CALL(op) (((op)==CEE_CALLI)||((op)==OP_CALL)||((op)==OP_CALLVIRT)||(((op)>=OP_VOIDCALL)&&((op)<=OP_CALL_MEMBASE)))
 #define OP_IS_STORE(op) (((op)==CEE_STIND_REF)||((op)==CEE_STIND_I1)||((op)==CEE_STIND_I2)||((op)==CEE_STIND_I4)||((op)==CEE_STIND_I8)||((op)==CEE_STIND_R4)||((op)==CEE_STIND_R8)||((op)==CEE_STIND_I))
 #define OP_IS_LOAD(op) (((op)==CEE_LDIND_REF)||((op)==CEE_LDIND_I1)||((op)==CEE_LDIND_I2)||((op)==CEE_LDIND_I4)||((op)==CEE_LDIND_U1)||((op)==CEE_LDIND_U2)||((op)==CEE_LDIND_U4)||((op)==CEE_LDIND_I8)||((op)==CEE_LDIND_R4)||((op)==CEE_LDIND_R8)||((op)==CEE_LDIND_I))
 #define OP_IS_CONST(op) (((op)==OP_ICONST)||((op)==OP_I8CONST)||((op)==OP_R4CONST)||((op)==OP_R8CONST)||((op)==OP_AOTCONST))
+#define OP_IS_ICONV(op) (((op)==CEE_CONV_I4)||((op)==CEE_CONV_U4)||((op)==CEE_CONV_I8)||((op)==CEE_CONV_U8)||\
+               ((op)==CEE_CONV_OVF_I4_UN)||((op)==CEE_CONV_OVF_I8_UN)||((op)==CEE_CONV_OVF_U4_UN)||((op)==CEE_CONV_OVF_U8_UN)||\
+               ((op)==CEE_CONV_OVF_I4)||((op)==CEE_CONV_OVF_U4)||((op)==CEE_CONV_OVF_I8)||((op)==CEE_CONV_OVF_U8)||\
+               ((op)==OP_LCONV_TO_I8)||((op)==OP_LCONV_TO_OVF_I8)||((op)==OP_LCONV_TO_OVF_I8_UN)||\
+               ((op)==OP_LCONV_TO_U8)||((op)==OP_LCONV_TO_OVF_U8)||((op)==OP_LCONV_TO_OVF_U8_UN))
+#define OP_IS_PCONV(op) (((op)==CEE_CONV_OVF_I_UN)||((op)==CEE_CONV_OVF_U_UN)||\
+               ((op)==CEE_CONV_I)||((op)==CEE_CONV_U)||\
+               ((op)==CEE_CONV_OVF_I)||((op)==CEE_CONV_OVF_U)||\
+               ((op)==OP_LCONV_TO_I)||((op)==OP_LCONV_TO_OVF_I)||((op)==OP_LCONV_TO_OVF_I_UN)||\
+               ((op)==OP_LCONV_TO_U)||((op)==OP_LCONV_TO_OVF_U)||((op)==OP_LCONV_TO_OVF_U_UN))
 #define LOAD_OF_LOCAL_GIVES_POINTER(load,local) ((local->opcode == OP_LOCAL) && (((load)->type == STACK_MP) || ((load)->type == STACK_PTR) || ((local)->inst_vtype->type == MONO_TYPE_PTR)))
 
+
 /*
  * A struct representing the context of the traversal of a MonoInst tree.
  * Used so that "update_aliasing_information_on_inst" can understand what
@@ -117,7 +126,7 @@ print_tree_node (MonoInst *tree) {
        printf (mono_inst_name (tree->opcode));
        
        if (OP_IS_OUTARG (tree->opcode)) {
-               printf ("[OUT:%d]", tree->inst_c1);
+               printf ("[OUT:%ld]", (long)tree->inst_c1);
        }
        
        switch (tree->opcode) {
@@ -149,8 +158,8 @@ print_tree_node (MonoInst *tree) {
        case CEE_NEWARR:
                printf ("[%s]",  tree->inst_newa_class->name);
                break;
-       case CEE_CALL:
-       case CEE_CALLVIRT:
+       case OP_CALL:
+       case OP_CALLVIRT:
        case OP_FCALL:
        case OP_FCALLVIRT:
        case OP_LCALL:
@@ -158,7 +167,8 @@ print_tree_node (MonoInst *tree) {
        case OP_VCALL:
        case OP_VCALLVIRT:
        case OP_VOIDCALL:
-       case OP_VOIDCALLVIRT: {
+       case OP_VOIDCALLVIRT:
+       case OP_TRAMPCALL_VTABLE: {
                MonoCallInst *call = (MonoCallInst*)tree;
                if (call->method)
                        printf ("[%s]", call->method->name);
@@ -190,7 +200,7 @@ print_tree_node (MonoInst *tree) {
        case OP_LOADI2_MEMBASE:
                printf ("[%s] <- [%s + 0x%x]", mono_arch_regname (tree->dreg), mono_arch_regname (tree->inst_basereg), (int)tree->inst_offset);
                break;
-       case CEE_BR:
+       case OP_BR:
        case OP_CALL_HANDLER:
                printf ("[B%d]", tree->inst_target_bb->block_num);
                break;
@@ -243,7 +253,7 @@ print_used_aliases(MonoInst *inst, MonoLocalVariableList* affected_variables) {
                        switch (inst->inst_i0->opcode) {
                        case OP_LOCAL:
                        case OP_ARG:
-                               printf ("{%d}", inst->inst_i0->inst_c0);
+                               printf ("{%ld}", (long)inst->inst_i0->inst_c0);
                                break;
                        case OP_RETARG:
                                printf ("{RETARG}");
@@ -305,7 +315,7 @@ print_code_with_aliasing_information (MonoAliasingInformation *info) {
                
                printf ("CODE FOR BB %d\n", bb_info->bb->block_num);
                mono_aliasing_initialize_code_traversal (info, bb_info->bb);
-               for (inst = bb_info->bb->code; inst != NULL; inst = inst->next) {
+               MONO_BB_FOR_EACH_INS (bb_info->bb, inst) {
                        print_tree_with_aliasing_information (info, inst);
                        printf ("\n");
                }
@@ -348,7 +358,7 @@ print_code_with_aliasing_information (MonoAliasingInformation *info) {
 #define ADD_ARGUMGENT(info,inst,alias) do {\
                if ((info)->number_of_arguments == (info)->arguments_capacity) {\
                        MonoInst **new_arguments = mono_mempool_alloc ((info)->mempool, sizeof (MonoInst*) * ((info)->arguments_capacity * 2));\
-                       MonoAliasValue *new_arguments_aliases = mono_mempool_alloc ((info)->mempool, sizeof (MonoInst*) * ((info)->arguments_capacity * 2));\
+                       MonoAliasValue *new_arguments_aliases = mono_mempool_alloc ((info)->mempool, sizeof (MonoAliasValue) * ((info)->arguments_capacity * 2));\
                        memcpy (new_arguments, (info)->arguments, sizeof (MonoInst*) * ((info)->arguments_capacity));\
                        memcpy (new_arguments_aliases, (info)->arguments_aliases, sizeof (MonoAliasValue) * ((info)->arguments_capacity));\
                        (info)->arguments = new_arguments;\
@@ -630,19 +640,31 @@ update_aliasing_information_on_inst (MonoAliasingInformation *info, MonoAliasing
                        use->affected_variables = info->temporary_uncontrollably_aliased_variables;
                        APPEND_USE (info,bb_info,use);
                }
-       } else if ((inst->opcode == OP_UNBOXCAST) || (inst->opcode == CEE_CONV_I)) {
+       } else if ((inst->opcode == OP_UNBOXCAST) || OP_IS_PCONV (inst->opcode) || OP_IS_ICONV (inst->opcode)) {
                father_alias->type = context.subtree_aliases [0].type;
                father_alias->variable_index = context.subtree_aliases [0].variable_index;
-       } else if ((inst->opcode == CEE_LDELEMA) || (inst->opcode == OP_COMPARE) || (inst->opcode == CEE_SWITCH)) {
+       } else if ((inst->opcode == CEE_LDELEMA) || (inst->opcode == OP_COMPARE) || (inst->opcode == OP_SWITCH)) {
                if (father_alias != NULL) {
                        father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
                }
        } else {
                MonoAliasType father_type = MONO_ALIASING_TYPE_NO_ALIAS;
                if ((context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL) || (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL_FIELD)) {
+                       MonoAliasUsageInformation *use = mono_mempool_alloc (info->mempool, sizeof (MonoAliasUsageInformation));
+                       
+                       inst->ssa_op = MONO_SSA_INDIRECT_LOAD_STORE;
+                       use->inst = inst;
+                       use->affected_variables = &(info->variables [context.subtree_aliases [0].variable_index]);
+                       APPEND_USE (info, bb_info, use);
                        ADD_BAD_ALIAS (info, context.subtree_aliases [0].variable_index);
                }
                if ((context.subtree_aliases [1].type == MONO_ALIASING_TYPE_LOCAL) || (context.subtree_aliases [1].type == MONO_ALIASING_TYPE_LOCAL_FIELD)) {
+                       MonoAliasUsageInformation *use = mono_mempool_alloc (info->mempool, sizeof (MonoAliasUsageInformation));
+                       
+                       inst->ssa_op = MONO_SSA_INDIRECT_LOAD_STORE;
+                       use->inst = inst;
+                       use->affected_variables = &(info->variables [context.subtree_aliases [1].variable_index]);
+                       APPEND_USE (info, bb_info, use);
                        ADD_BAD_ALIAS (info, context.subtree_aliases [1].variable_index);
                }
                if (father_alias != NULL) { 
@@ -712,7 +734,7 @@ mono_build_aliasing_information (MonoCompile *cfg) {
                bb_info->potential_alias_uses = NULL;
                info->next_interesting_inst = NULL;
                
-               for (inst = bb->code; inst != NULL; inst = inst->next) {
+               MONO_BB_FOR_EACH_INS (bb, inst) {
                        if (FOLLOW_ALIAS_ANALYSIS) {
                                printf ("TRAVERSING INST: ");
                                mono_print_tree_nl (inst);
@@ -736,7 +758,7 @@ mono_build_aliasing_information (MonoCompile *cfg) {
                                } else {
                                        MonoLocalVariableList *last = use->affected_variables;
                                        while (last->next != NULL) {
-                                               while (info->variable_is_uncontrollably_aliased [last->next->variable_index]) {
+                                               while (last->next && info->variable_is_uncontrollably_aliased [last->next->variable_index]) {
                                                        last->next = last->next->next;
                                                }
                                                if (last->next != NULL) {
@@ -805,7 +827,8 @@ mono_aliasing_get_affected_variables_for_inst_traversing_code (MonoAliasingInfor
        }
 }
 
-MonoLocalVariableList*
+#if 0
+static MonoLocalVariableList*
 mono_aliasing_get_affected_variables_for_inst_in_bb (MonoAliasingInformation *info, MonoInst *inst, MonoBasicBlock *bb) {
        MonoAliasUsageInformation *use;
        
@@ -817,6 +840,7 @@ mono_aliasing_get_affected_variables_for_inst_in_bb (MonoAliasingInformation *in
        g_assert_not_reached ();
        return NULL;
 }
+#endif
 
 MonoLocalVariableList*
 mono_aliasing_get_affected_variables_for_inst (MonoAliasingInformation *info, MonoInst *inst) {
@@ -875,10 +899,17 @@ mono_aliasing_deadce_on_inst (MonoAliasingInformation *info, MonoInst **possibly
        
        arity = mono_burg_arity [inst->opcode];
        
-       if (OP_IS_CALL (inst->opcode)) {
-               has_side_effects = TRUE;
-       } else {
+       switch (inst->opcode) {
+#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
                has_side_effects = FALSE;
+               break;
+       default:
+               has_side_effects = TRUE;
        }
        
        if (arity) {
@@ -914,7 +945,7 @@ mono_aliasing_deadce_on_inst (MonoAliasingInformation *info, MonoInst **possibly
                                                printf ("KILLING slot %d at inst ", affected_variable->variable_index);
                                                mono_print_tree_nl (inst);
                                        }
-                                       possibly_dead_assignments [affected_variable->variable_index]->opcode = CEE_NOP;
+                                       possibly_dead_assignments [affected_variable->variable_index]->opcode = OP_NOP;
                                        possibly_dead_assignments [affected_variable->variable_index]->ssa_op = MONO_SSA_NOP;
                                        possibly_dead_assignments [affected_variable->variable_index] = NULL;
                                }
@@ -927,7 +958,7 @@ mono_aliasing_deadce_on_inst (MonoAliasingInformation *info, MonoInst **possibly
        
        if ((! has_side_effects) && (inst->ssa_op == MONO_SSA_STORE)) {
                if (LOG_DEADCE) {
-                       printf ("FILLING slot %d with inst ", inst->inst_i0->inst_c0);
+                       printf ("FILLING slot %d with inst ", (int)inst->inst_i0->inst_c0);
                        mono_print_tree_nl (inst);
                }
                possibly_dead_assignments [inst->inst_i0->inst_c0] = inst;
@@ -975,9 +1006,9 @@ mono_aliasing_deadce (MonoAliasingInformation *info) {
                        printf ("Working on BB %d\n", bb->block_num);
                }
                
-               for (inst = bb->code; inst != NULL; inst = inst->next) {
+               MONO_BB_FOR_EACH_INS (bb, inst) {
                        mono_aliasing_deadce_on_inst (info, possibly_dead_assignments, inst);
-                       if (inst->opcode == CEE_JMP) {
+                       if (inst->opcode == OP_JMP) {
                                /* Keep arguments live! */
                                for (variable_index = 0; variable_index < cfg->num_varinfo; variable_index++) {
                                        if (cfg->varinfo [variable_index]->opcode == OP_ARG) {
@@ -1000,7 +1031,7 @@ mono_aliasing_deadce (MonoAliasingInformation *info) {
                                
                                //printf ("FAST DEADCE DEAD LOCAL\n");
                                
-                               possibly_dead_assignments [variable_index]->opcode = CEE_NOP;
+                               possibly_dead_assignments [variable_index]->opcode = OP_NOP;
                                possibly_dead_assignments [variable_index]->ssa_op = MONO_SSA_NOP;
                        }
                }