#include "aliasing.h"
-extern guint8 mono_burg_arity [];
-
#define MONO_APPLY_DEADCE_TO_SINGLE_METHOD 0
#define DEBUG_DEADCE 0
#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
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:
case OP_VCALL:
case OP_VCALLVIRT:
case OP_VOIDCALL:
- case OP_VOIDCALLVIRT: {
+ case OP_VOIDCALLVIRT:
+ case OP_TRAMPCALL_VTABLE:
+ case OP_CALL_RGCTX:
+ case OP_FCALL_RGCTX:
+ case OP_VOIDCALL_RGCTX:
+ case OP_LCALL_RGCTX:
+ case OP_VCALL_RGCTX:
+ case OP_CALL_REG_RGCTX:
+ case OP_FCALL_REG_RGCTX:
+ case OP_VOIDCALL_REG_RGCTX:
+ case OP_LCALL_REG_RGCTX:
+ case OP_VCALL_REG_RGCTX:
+ case OP_CALLVIRT_IMT:
+ case OP_VOIDCALLVIRT_IMT:
+ case OP_FCALLVIRT_IMT:
+ case OP_LCALLVIRT_IMT:
+ case OP_VCALLVIRT_IMT: {
MonoCallInst *call = (MonoCallInst*)tree;
if (call->method)
printf ("[%s]", call->method->name);
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;
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");
}
#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;\
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;
+ MonoLocalVariableList *affected_variables = NULL;
+
if ((context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL) || (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL_FIELD)) {
+ affected_variables = &(info->variables [context.subtree_aliases [0].variable_index]);
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)) {
+ if (affected_variables == NULL) {
+ affected_variables = &(info->variables [context.subtree_aliases [1].variable_index]);
+ } else if (affected_variables->variable_index != context.subtree_aliases [1].variable_index) {
+ int previous_index = affected_variables->variable_index;
+ affected_variables = NULL;
+ ADD_UNIQUE_VARIABLE (info, affected_variables, previous_index);
+ ADD_UNIQUE_VARIABLE (info, affected_variables, context.subtree_aliases [1].variable_index);
+ }
ADD_BAD_ALIAS (info, context.subtree_aliases [1].variable_index);
}
+
+ if (affected_variables != NULL) {
+ MonoAliasUsageInformation *use = mono_mempool_alloc (info->mempool, sizeof (MonoAliasUsageInformation));
+
+ inst->ssa_op = MONO_SSA_INDIRECT_LOAD_STORE;
+ use->inst = inst;
+ use->affected_variables = affected_variables;
+ APPEND_USE (info, bb_info, use);
+ }
+
if (father_alias != NULL) {
if ((context.subtree_aliases [0].type == MONO_ALIASING_TYPE_ANY) || (context.subtree_aliases [1].type == MONO_ALIASING_TYPE_ANY)) {
father_type = MONO_ALIASING_TYPE_ANY;
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);
}
}
-MonoLocalVariableList*
+#if 0
+static MonoLocalVariableList*
mono_aliasing_get_affected_variables_for_inst_in_bb (MonoAliasingInformation *info, MonoInst *inst, MonoBasicBlock *bb) {
MonoAliasUsageInformation *use;
g_assert_not_reached ();
return NULL;
}
+#endif
MonoLocalVariableList*
mono_aliasing_get_affected_variables_for_inst (MonoAliasingInformation *info, MonoInst *inst) {
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) {
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;
}
possibly_dead_assignments = alloca (cfg->num_varinfo * sizeof (MonoInst*));
if (LOG_DEADCE) {
- printf ("BEFORE DEADCE START\n");
- mono_print_code (cfg);
- printf ("BEFORE DEADCE END\n");
+ mono_print_code (cfg, "BEFORE DEADCE START");
}
#if (MONO_APPLY_DEADCE_TO_SINGLE_METHOD)
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) {
//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;
}
}
}
if (LOG_DEADCE) {
- printf ("AFTER DEADCE START\n");
- mono_print_code (cfg);
- printf ("AFTER DEADCE END\n");
+ mono_print_code (cfg, "AFTER DEADCE");
}
}