2 * aliasing.c: Alias Analysis
5 * Massimiliano Mantione (massi@ximian.com)
7 * (C) 2005 Novell, Inc. http://www.novell.com
12 #include <mono/metadata/debug-helpers.h>
13 #include <mono/metadata/mempool.h>
14 #include <mono/metadata/opcodes.h>
18 #define MONO_APPLY_DEADCE_TO_SINGLE_METHOD 0
19 #define DEBUG_DEADCE 0
21 #define DEBUG_ALIAS_ANALYSIS 0
23 #define TRACE_ALIAS_ANALYSIS (info->cfg->verbose_level > 2)
24 #define DUMP_ALIAS_ANALYSIS (info->cfg->verbose_level > 4)
25 #define FOLLOW_ALIAS_ANALYSIS (info->cfg->verbose_level > 5)
27 static const char *mono_aliasing_value_names[] = {
35 static const char *mono_stack_type_names[] = {
47 #define NO_VARIABLE_INDEX MONO_ALIASING_INVALID_VARIABLE_INDEX
50 #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))
51 #define OP_IS_CALL(op) (((op)==CEE_CALLI)||((op)==CEE_CALL)||((op)==CEE_CALLVIRT)||(((op)>=OP_VOIDCALL)&&((op)<=OP_CALL_MEMBASE)))
52 #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))
53 #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))
54 #define OP_IS_CONST(op) (((op)==OP_ICONST)||((op)==OP_I8CONST)||((op)==OP_R4CONST)||((op)==OP_R8CONST)||((op)==OP_AOTCONST))
55 #define OP_IS_ICONV(op) (((op)==CEE_CONV_I4)||((op)==CEE_CONV_U4)||((op)==CEE_CONV_I8)||((op)==CEE_CONV_U8)||\
56 ((op)==CEE_CONV_OVF_I4_UN)||((op)==CEE_CONV_OVF_I8_UN)||((op)==CEE_CONV_OVF_U4_UN)||((op)==CEE_CONV_OVF_U8_UN)||\
57 ((op)==CEE_CONV_OVF_I4)||((op)==CEE_CONV_OVF_U4)||((op)==CEE_CONV_OVF_I8)||((op)==CEE_CONV_OVF_U8)||\
58 ((op)==OP_LCONV_TO_I8)||((op)==OP_LCONV_TO_OVF_I8)||((op)==OP_LCONV_TO_OVF_I8_UN)||\
59 ((op)==OP_LCONV_TO_U8)||((op)==OP_LCONV_TO_OVF_U8)||((op)==OP_LCONV_TO_OVF_U8_UN))
60 #define OP_IS_PCONV(op) (((op)==CEE_CONV_OVF_I_UN)||((op)==CEE_CONV_OVF_U_UN)||\
61 ((op)==CEE_CONV_I)||((op)==CEE_CONV_U)||\
62 ((op)==CEE_CONV_OVF_I)||((op)==CEE_CONV_OVF_U)||\
63 ((op)==OP_LCONV_TO_I)||((op)==OP_LCONV_TO_OVF_I)||((op)==OP_LCONV_TO_OVF_I_UN)||\
64 ((op)==OP_LCONV_TO_U)||((op)==OP_LCONV_TO_OVF_U)||((op)==OP_LCONV_TO_OVF_U_UN))
65 #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)))
69 * A struct representing the context of the traversal of a MonoInst tree.
70 * Used so that "update_aliasing_information_on_inst" can understand what
71 * its caller was doing, and expecially where the current value is going
72 * to be stored (if it is an alias, we must track it).
74 typedef struct MonoAliasingInformationContext {
77 MonoAliasValue subtree_aliases [2];
79 struct MonoAliasingInformationContext *father;
80 } MonoAliasingInformationContext;
84 print_alias_value (MonoAliasValue *alias_value) {
85 printf ("[%s", mono_aliasing_value_names [alias_value->type]);
86 if ((alias_value->type == MONO_ALIASING_TYPE_LOCAL) || (alias_value->type == MONO_ALIASING_TYPE_LOCAL_FIELD)) {
87 printf (":%d]", alias_value->variable_index);
94 print_ssaop_value (int ssaop_value) {
96 if (ssaop_value & MONO_SSA_ADDRESS_TAKEN) printf ("I"); else printf (".");
97 if (ssaop_value & MONO_SSA_LOAD) printf ("R"); else printf (".");
98 if (ssaop_value & MONO_SSA_STORE) printf ("W"); else printf (".");
103 print_aliasing_context (MonoAliasingInformationContext *context) {
104 printf ("CONTEXT: left ");
105 print_alias_value (&(context->subtree_aliases [0]));
107 print_alias_value (&(context->subtree_aliases [1]));
108 if (context->father != NULL) {
109 printf (", father ");
110 print_alias_value (&(context->father->subtree_aliases [context->father->current_subtree]));
112 printf (", stack %s ", mono_stack_type_names [context->inst->type]);
113 if (context->inst->ssa_op != MONO_SSA_NOP) {
114 print_ssaop_value (context->inst->ssa_op);
118 mono_print_tree_nl (context->inst);
122 print_tree_node (MonoInst *tree) {
126 printf (mono_inst_name (tree->opcode));
128 if (OP_IS_OUTARG (tree->opcode)) {
129 printf ("[OUT:%ld]", (long)tree->inst_c1);
132 switch (tree->opcode) {
134 printf ("[%d]", (int)tree->inst_c0);
137 printf ("[%lld]", (long long)tree->inst_l);
140 printf ("[%f]", *(double*)tree->inst_p0);
143 printf ("[%f]", *(float*)tree->inst_p0);
147 printf ("[%d]", (int)tree->inst_c0);
150 if (tree->inst_offset < 0)
151 printf ("[-0x%x(%s)]", (int)(-tree->inst_offset), mono_arch_regname (tree->inst_basereg));
153 printf ("[0x%x(%s)]", (int)(tree->inst_offset), mono_arch_regname (tree->inst_basereg));
156 printf ("[%s]", mono_arch_regname (tree->dreg));
159 printf ("[%s]", tree->inst_newa_class->name);
170 case OP_VOIDCALLVIRT:
171 case OP_TRAMPCALL_VTABLE: {
172 MonoCallInst *call = (MonoCallInst*)tree;
174 printf ("[%s]", call->method->name);
175 else if (call->fptr) {
176 MonoJitICallInfo *info = mono_find_jit_icall_by_addr (call->fptr);
178 printf ("[%s]", info->name);
180 printf ("[ARGS:%d]", call->signature->param_count);
185 printf ("[%d (", (int)tree->inst_c0);
186 for (i = 0; i < tree->inst_phi_args [0]; i++) {
189 printf ("%d", tree->inst_phi_args [i + 1]);
194 case OP_LOAD_MEMBASE:
195 case OP_LOADI4_MEMBASE:
196 case OP_LOADU4_MEMBASE:
197 case OP_LOADU1_MEMBASE:
198 case OP_LOADI1_MEMBASE:
199 case OP_LOADU2_MEMBASE:
200 case OP_LOADI2_MEMBASE:
201 printf ("[%s] <- [%s + 0x%x]", mono_arch_regname (tree->dreg), mono_arch_regname (tree->inst_basereg), (int)tree->inst_offset);
204 case OP_CALL_HANDLER:
205 printf ("[B%d]", tree->inst_target_bb->block_num);
217 printf ("[B%dB%d]", tree->inst_true_bb->block_num, tree->inst_false_bb->block_num);
220 printf ("[%d]", (int)tree->inst_i0->inst_i0->inst_c0);
223 printf ("[%d]", (int)tree->inst_i0->inst_c0);
231 print_variable_list (MonoLocalVariableList* variables) {
233 while (variables != NULL) {
234 printf ("%d", variables->variable_index);
235 if (variables->next != NULL) {
238 variables = variables->next;
244 print_used_aliases(MonoInst *inst, MonoLocalVariableList* affected_variables) {
245 if (inst->ssa_op != MONO_SSA_NOP) {
247 if (inst->ssa_op & MONO_SSA_ADDRESS_TAKEN) printf ("I");
248 if (inst->ssa_op & MONO_SSA_LOAD) printf ("R");
249 if (inst->ssa_op & MONO_SSA_STORE) printf ("W");
250 if (inst->ssa_op != MONO_SSA_ADDRESS_TAKEN) {
251 print_variable_list (affected_variables);
253 switch (inst->inst_i0->opcode) {
256 printf ("{%ld}", (long)inst->inst_i0->inst_c0);
271 print_tree_with_aliasing_information (MonoAliasingInformation *info, MonoInst *tree) {
273 MonoLocalVariableList* affected_variables;
276 printf ("NULL-INST");
280 arity = mono_burg_arity [tree->opcode];
282 print_tree_node (tree);
284 if (OP_IS_CALL (tree->opcode) && arity) {
290 print_tree_with_aliasing_information (info, tree->inst_i0);
293 print_tree_with_aliasing_information (info, tree->inst_i1);
298 affected_variables = mono_aliasing_get_affected_variables_for_inst_traversing_code (info, tree);
299 print_used_aliases (tree, affected_variables);
303 print_code_with_aliasing_information (MonoAliasingInformation *info) {
304 char *name = mono_method_full_name (info->cfg->method, TRUE);
307 printf ("ALIASING DATA START (METHOD %s)\n", name);
308 printf ("ALIASED VARIABLES: ");
309 print_variable_list (info->uncontrollably_aliased_variables);
311 for (i = 0; i < info->cfg->num_bblocks; i++) {
312 MonoAliasingInformationInBB *bb_info = &(info->bb [i]);
313 MonoAliasUsageInformation *use;
316 printf ("CODE FOR BB %d\n", bb_info->bb->block_num);
317 mono_aliasing_initialize_code_traversal (info, bb_info->bb);
318 for (inst = bb_info->bb->code; inst != NULL; inst = inst->next) {
319 print_tree_with_aliasing_information (info, inst);
323 printf ("USES FOR BB %d\n", bb_info->bb->block_num);
324 for (use = bb_info->potential_alias_uses; use != NULL; use = use->next) {
325 mono_print_tree (use->inst);
326 print_used_aliases (use->inst, use->affected_variables);
330 printf ("ALIASING DATA END (METHOD %s)\n", name);
335 #define APPEND_USE(info,bb_info,use) do {\
337 if ((info)->next_interesting_inst != NULL) {\
338 (info)->next_interesting_inst->next = (use);\
340 (bb_info)->potential_alias_uses = (use);\
342 (info)->next_interesting_inst = (use);\
345 #define ADD_BAD_ALIAS(info,vi) do {\
346 if (FOLLOW_ALIAS_ANALYSIS) {\
347 printf ("ADDING BAD ALIAS FOR VARIABLE %d\n", vi);\
349 if (! ((info)->variable_is_uncontrollably_aliased [(vi)])) {\
350 MonoLocalVariableList *variable = mono_mempool_alloc ((info)->mempool, sizeof (MonoLocalVariableList));\
351 variable->variable_index = (vi);\
352 variable->next = (info)->uncontrollably_aliased_variables;\
353 (info)->uncontrollably_aliased_variables = variable;\
354 (info)->variable_is_uncontrollably_aliased [(vi)] = TRUE;\
358 #define ADD_ARGUMGENT(info,inst,alias) do {\
359 if ((info)->number_of_arguments == (info)->arguments_capacity) {\
360 MonoInst **new_arguments = mono_mempool_alloc ((info)->mempool, sizeof (MonoInst*) * ((info)->arguments_capacity * 2));\
361 MonoAliasValue *new_arguments_aliases = mono_mempool_alloc ((info)->mempool, sizeof (MonoAliasValue) * ((info)->arguments_capacity * 2));\
362 memcpy (new_arguments, (info)->arguments, sizeof (MonoInst*) * ((info)->arguments_capacity));\
363 memcpy (new_arguments_aliases, (info)->arguments_aliases, sizeof (MonoAliasValue) * ((info)->arguments_capacity));\
364 (info)->arguments = new_arguments;\
365 (info)->arguments_aliases = new_arguments_aliases;\
366 (info)->arguments_capacity = (info)->arguments_capacity * 2;\
368 (info)->arguments [(info)->number_of_arguments] = (inst);\
369 (info)->arguments_aliases [(info)->number_of_arguments] = (alias);\
370 (info)->number_of_arguments ++;\
373 #define ADD_UNIQUE_VARIABLE(info,list,vi) do {\
374 MonoLocalVariableList* target_element = (list);\
375 while ((target_element != NULL) && (target_element->variable_index != (vi))) {\
376 target_element = target_element->next;\
378 if (target_element == NULL) {\
379 target_element = mono_mempool_alloc ((info)->mempool, sizeof (MonoLocalVariableList));\
380 target_element->variable_index = (vi);\
381 target_element->next = (list);\
382 (list) = target_element;\
387 update_aliasing_information_on_inst (MonoAliasingInformation *info, MonoAliasingInformationInBB *bb_info, MonoInst *inst, MonoAliasingInformationContext *father_context) {
388 MonoAliasingInformationContext context;
389 MonoAliasValue *father_alias;
392 context.father = father_context;
393 if (father_context != NULL) {
394 father_alias = &(father_context->subtree_aliases [father_context->current_subtree]);
399 if (mono_burg_arity [inst->opcode]) {
400 context.current_subtree = 0;
401 context.subtree_aliases [0].type = MONO_ALIASING_TYPE_ANY;
402 context.subtree_aliases [0].variable_index = NO_VARIABLE_INDEX;
403 update_aliasing_information_on_inst (info, bb_info, inst->inst_i0, &context);
405 if (mono_burg_arity [inst->opcode] > 1) {
406 context.current_subtree = 1;
407 context.subtree_aliases [1].type = MONO_ALIASING_TYPE_ANY;
408 context.subtree_aliases [1].variable_index = NO_VARIABLE_INDEX;
409 update_aliasing_information_on_inst (info, bb_info, inst->inst_i1, &context);
411 context.subtree_aliases [1].type = MONO_ALIASING_TYPE_NO_ALIAS;
414 context.subtree_aliases [0].type = MONO_ALIASING_TYPE_NO_ALIAS;
415 context.subtree_aliases [1].type = MONO_ALIASING_TYPE_NO_ALIAS;
418 if (OP_IS_CONST (inst->opcode)) {
419 father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
420 } else if (inst->ssa_op == MONO_SSA_ADDRESS_TAKEN) {
421 MonoInst *local = inst->inst_i0;
422 if ((local->opcode == OP_LOCAL) || (local->opcode == OP_ARG)) {
423 gssize variable_index = local->inst_c0;
424 father_alias->type = MONO_ALIASING_TYPE_LOCAL;
425 father_alias->variable_index = variable_index;
426 } else if (local->opcode == OP_RETARG) {
427 father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
429 father_alias->type = MONO_ALIASING_TYPE_ANY;
431 } else if (inst->ssa_op == MONO_SSA_LOAD) {
432 MonoInst *local = inst->inst_i0;
434 if (LOAD_OF_LOCAL_GIVES_POINTER (inst,local)) {
435 father_alias->type = MONO_ALIASING_TYPE_ANY;
437 father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
439 } else if (OP_IS_LOAD (inst->opcode) || (inst->opcode == CEE_LDOBJ)) {
440 MonoInst *address = inst->inst_i0;
441 MonoLocalVariableList *affected_variables = NULL;
443 if ((address->opcode == OP_LOCAL) || (address->opcode == OP_ARG)) {
444 gssize variable_index = address->inst_c0;
445 MonoInst *local = info->cfg->varinfo [variable_index];
447 affected_variables = &(info->variables [variable_index]);
448 if (LOAD_OF_LOCAL_GIVES_POINTER (inst,local)) {
449 father_alias->type = MONO_ALIASING_TYPE_ANY;
451 father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
453 } else if (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL) {
454 gssize variable_index = context.subtree_aliases [0].variable_index;
455 MonoInst *local = info->cfg->varinfo [variable_index];
457 affected_variables = &(info->variables [variable_index]);;
458 if (LOAD_OF_LOCAL_GIVES_POINTER (inst,local)) {
459 father_alias->type = MONO_ALIASING_TYPE_ANY;
461 father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
463 } else if (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL_FIELD) {
464 gssize variable_index = context.subtree_aliases [0].variable_index;
466 affected_variables = &(info->variables [variable_index]);;
467 if (inst->type == STACK_MP) {
468 father_alias->type = MONO_ALIASING_TYPE_ANY;
470 father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
473 if (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_ANY) {
474 affected_variables = info->temporary_uncontrollably_aliased_variables;
476 if ((inst->type == STACK_MP) && (inst->inst_i0->opcode != OP_OBJADDR)) {
477 father_alias->type = MONO_ALIASING_TYPE_ANY;
479 father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
483 if (affected_variables != NULL) {
484 MonoAliasUsageInformation *use = mono_mempool_alloc (info->mempool, sizeof (MonoAliasUsageInformation));
486 inst->ssa_op = MONO_SSA_INDIRECT_LOAD;
488 use->affected_variables = affected_variables;
489 APPEND_USE (info,bb_info,use);
491 } else if (inst->ssa_op == MONO_SSA_STORE) {
492 if (context.subtree_aliases [1].type == MONO_ALIASING_TYPE_LOCAL) {
493 ADD_BAD_ALIAS (info, context.subtree_aliases [1].variable_index);
495 } else if (OP_IS_STORE (inst->opcode) || (inst->opcode == CEE_STOBJ)) {
496 MonoInst *address = inst->inst_i0;
497 MonoLocalVariableList *affected_variables = NULL;
499 if (context.subtree_aliases [1].type == MONO_ALIASING_TYPE_LOCAL) {
500 ADD_BAD_ALIAS (info, context.subtree_aliases [1].variable_index);
503 if ((address->opcode == OP_LOCAL) || (address->opcode == OP_ARG)) {
504 gssize variable_index = address->inst_c0;
506 affected_variables = &(info->variables [variable_index]);
507 } else if ((context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL) || (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL_FIELD)) {
508 gssize variable_index = context.subtree_aliases [0].variable_index;
510 affected_variables = &(info->variables [variable_index]);;
511 } else if (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_ANY) {
512 affected_variables = info->temporary_uncontrollably_aliased_variables;
515 if (affected_variables != NULL) {
516 MonoAliasUsageInformation *use = mono_mempool_alloc (info->mempool, sizeof (MonoAliasUsageInformation));
518 inst->ssa_op = MONO_SSA_INDIRECT_STORE;
520 use->affected_variables = affected_variables;
521 APPEND_USE (info,bb_info,use);
523 } else if (OP_IS_OUTARG (inst->opcode)) {
524 ADD_ARGUMGENT (info,inst,context.subtree_aliases [0]);
525 } else if (OP_IS_CALL (inst->opcode)) {
526 MonoCallInst *call = (MonoCallInst *) inst;
527 MonoMethodSignature *sig = call->signature;
528 gboolean call_has_untracked_pointer_argument = FALSE;
529 MonoLocalVariableList *alias_arguments = NULL;
532 if ((context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL) || (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL_FIELD)) {
533 ADD_UNIQUE_VARIABLE (info,alias_arguments,context.subtree_aliases [0].variable_index);
534 } else if (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_ANY) {
535 call_has_untracked_pointer_argument = TRUE;
538 if (FOLLOW_ALIAS_ANALYSIS) {
539 printf ("CALL, scanning %d arguments\n", info->number_of_arguments);
541 for (i = 0; i < info->number_of_arguments; i++) {
543 //MonoInst *argument = info->arguments [i];
544 MonoAliasValue arguments_alias = info->arguments_aliases [i];
546 if ((arguments_alias.type == MONO_ALIASING_TYPE_LOCAL) || (arguments_alias.type == MONO_ALIASING_TYPE_LOCAL_FIELD)) {
547 if (FOLLOW_ALIAS_ANALYSIS) {
548 printf ("CALL, argument %d passes the address of local %d\n", i, arguments_alias.variable_index);
550 ADD_UNIQUE_VARIABLE (info,alias_arguments,arguments_alias.variable_index);
553 if (((arguments_alias.type == MONO_ALIASING_TYPE_LOCAL)) && (argument->inst_c1 > 0)) {
554 int argument_index = argument->inst_c1 - 1;
555 if (argument_index < sig->param_count) {
556 if (! (sig->params [argument_index]->byref)) {
557 ADD_BAD_ALIAS (info, arguments_alias.variable_index);
560 printf ("*** ERROR: argument %d of %d: ", argument_index, sig->param_count);
561 mono_print_tree_nl (argument);
565 } else if (arguments_alias.type == MONO_ALIASING_TYPE_ANY) {
566 if (FOLLOW_ALIAS_ANALYSIS) {
567 printf ("CALL, argument %d could pass the address of any local\n", i);
569 call_has_untracked_pointer_argument = TRUE;
573 else if (argument->inst_c1 > 0) {
574 int argument_index = argument->inst_c1 - 1;
575 if (argument_index < sig->param_count) {
576 if (sig->params [argument_index]->type == MONO_TYPE_PTR) {
577 call_has_untracked_pointer_argument = TRUE;
580 printf ("*** ERROR: argument %d of %d: ", argument_index, sig->param_count);
581 mono_print_tree_nl (argument);
587 if ((alias_arguments != NULL) || call_has_untracked_pointer_argument) {
588 MonoAliasUsageInformation *use = mono_mempool_alloc (info->mempool, sizeof (MonoAliasUsageInformation));
590 inst->ssa_op = MONO_SSA_INDIRECT_LOAD_STORE;
592 use->affected_variables = alias_arguments;
593 if (call_has_untracked_pointer_argument) {
594 MonoLocalVariableList *untracked_element = mono_mempool_alloc ((info)->mempool, sizeof (MonoLocalVariableList));
595 untracked_element->variable_index = NO_VARIABLE_INDEX;
596 untracked_element->next = use->affected_variables;
597 use->affected_variables = untracked_element;
599 APPEND_USE (info,bb_info,use);
602 if ((sig->ret != NULL) && (father_alias != NULL)) {
603 if (sig->ret->type != MONO_TYPE_PTR) {
604 father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
606 father_alias->type = MONO_ALIASING_TYPE_ANY;
610 info->number_of_arguments = 0;
611 } else if ((inst->opcode == CEE_ADD) || (inst->opcode == OP_LADD)){
612 if ((context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL) || (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL_FIELD)) {
613 int variable_index = context.subtree_aliases [0].variable_index;
614 //ADD_BAD_ALIAS (info, variable_index);
615 father_alias->type = MONO_ALIASING_TYPE_LOCAL_FIELD;
616 father_alias->variable_index = variable_index;
617 } else if ((context.subtree_aliases [1].type == MONO_ALIASING_TYPE_LOCAL) || (context.subtree_aliases [1].type == MONO_ALIASING_TYPE_LOCAL_FIELD)) {
618 int variable_index = context.subtree_aliases [1].variable_index;
619 //ADD_BAD_ALIAS (info, variable_index);
620 father_alias->type = MONO_ALIASING_TYPE_LOCAL_FIELD;
621 father_alias->variable_index = variable_index;
622 } else if ((context.subtree_aliases [0].type == MONO_ALIASING_TYPE_ANY) || (context.subtree_aliases [1].type == MONO_ALIASING_TYPE_ANY)) {
623 father_alias->type = MONO_ALIASING_TYPE_ANY;
625 father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
627 } else if ((inst->opcode == OP_MEMCPY) || (inst->opcode == OP_MEMSET)) {
628 if ((context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL) || (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL_FIELD)) {
629 MonoAliasUsageInformation *use = mono_mempool_alloc (info->mempool, sizeof (MonoAliasUsageInformation));
631 inst->ssa_op = MONO_SSA_INDIRECT_STORE;
633 use->affected_variables = &(info->variables [context.subtree_aliases [0].variable_index]);
634 APPEND_USE (info,bb_info,use);
635 } else if (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_ANY) {
636 MonoAliasUsageInformation *use = mono_mempool_alloc (info->mempool, sizeof (MonoAliasUsageInformation));
638 inst->ssa_op = MONO_SSA_INDIRECT_STORE;
640 use->affected_variables = info->temporary_uncontrollably_aliased_variables;
641 APPEND_USE (info,bb_info,use);
643 } else if ((inst->opcode == OP_UNBOXCAST) || OP_IS_PCONV (inst->opcode) || OP_IS_ICONV (inst->opcode)) {
644 father_alias->type = context.subtree_aliases [0].type;
645 father_alias->variable_index = context.subtree_aliases [0].variable_index;
646 } else if ((inst->opcode == CEE_LDELEMA) || (inst->opcode == OP_COMPARE) || (inst->opcode == CEE_SWITCH)) {
647 if (father_alias != NULL) {
648 father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
651 MonoAliasType father_type = MONO_ALIASING_TYPE_NO_ALIAS;
652 if ((context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL) || (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL_FIELD)) {
653 MonoAliasUsageInformation *use = mono_mempool_alloc (info->mempool, sizeof (MonoAliasUsageInformation));
655 inst->ssa_op = MONO_SSA_INDIRECT_LOAD_STORE;
657 use->affected_variables = &(info->variables [context.subtree_aliases [0].variable_index]);
658 APPEND_USE (info, bb_info, use);
659 ADD_BAD_ALIAS (info, context.subtree_aliases [0].variable_index);
661 if ((context.subtree_aliases [1].type == MONO_ALIASING_TYPE_LOCAL) || (context.subtree_aliases [1].type == MONO_ALIASING_TYPE_LOCAL_FIELD)) {
662 MonoAliasUsageInformation *use = mono_mempool_alloc (info->mempool, sizeof (MonoAliasUsageInformation));
664 inst->ssa_op = MONO_SSA_INDIRECT_LOAD_STORE;
666 use->affected_variables = &(info->variables [context.subtree_aliases [1].variable_index]);
667 APPEND_USE (info, bb_info, use);
668 ADD_BAD_ALIAS (info, context.subtree_aliases [1].variable_index);
670 if (father_alias != NULL) {
671 if ((context.subtree_aliases [0].type == MONO_ALIASING_TYPE_ANY) || (context.subtree_aliases [1].type == MONO_ALIASING_TYPE_ANY)) {
672 father_type = MONO_ALIASING_TYPE_ANY;
674 father_alias->type = father_type;
678 if (FOLLOW_ALIAS_ANALYSIS) {
679 print_aliasing_context (&context);
686 * mono_build_aliasing_information:
687 * @cfg: Control Flow Graph
689 * Builds the aliasing information in a cfg.
690 * After this has run, all MonoInst.ssa_op fields will be properly
691 * set (it will use the MONO_SSA_ADDRESS_TAKEN, MONO_SSA_LOAD and
692 * MONO_SSA_STORE values as a starting point).
694 MonoAliasingInformation*
695 mono_build_aliasing_information (MonoCompile *cfg) {
696 MonoMemPool *pool = mono_mempool_new ();
697 MonoAliasingInformation *info = mono_mempool_alloc (pool, sizeof (MonoAliasingInformation));
699 #if (DEBUG_ALIAS_ANALYSIS)
700 int verbose_level = cfg->verbose_level;
701 cfg->verbose_level = 7;
704 info->mempool = pool;
706 info->bb = mono_mempool_alloc (pool, sizeof (MonoAliasingInformationInBB) * cfg->num_bblocks);
707 info->uncontrollably_aliased_variables = NULL;
708 info->next_interesting_inst = NULL;
709 info->variables = mono_mempool_alloc (pool, sizeof (MonoLocalVariableList) * cfg->num_varinfo);
710 info->variable_is_uncontrollably_aliased = mono_mempool_alloc (pool, sizeof (gboolean) * cfg->num_varinfo);
711 for (i = 0; i < cfg->num_varinfo; i++) {
712 info->variables [i].next = NULL;
713 info->variables [i].variable_index = i;
714 info->variable_is_uncontrollably_aliased [i] = FALSE;
716 info->temporary_uncontrollably_aliased_variables = mono_mempool_alloc (pool, sizeof (MonoLocalVariableList));
717 info->temporary_uncontrollably_aliased_variables->next = NULL;
718 info->temporary_uncontrollably_aliased_variables->variable_index = NO_VARIABLE_INDEX;
719 info->arguments = mono_mempool_alloc (pool, sizeof (MonoInst*) * 16);
720 info->arguments_aliases = mono_mempool_alloc (pool, sizeof (MonoAliasValue) * 16);
721 info->arguments_capacity = 16;
722 info->number_of_arguments = 0;
724 for (i = 0; i < cfg->num_bblocks; i++) {
725 MonoBasicBlock *bb = cfg->bblocks [i];
726 MonoAliasingInformationInBB *bb_info = &(info->bb [i]);
729 if (FOLLOW_ALIAS_ANALYSIS) {
730 printf ("TRAVERSING BB %d\n", bb->block_num);
734 bb_info->potential_alias_uses = NULL;
735 info->next_interesting_inst = NULL;
737 for (inst = bb->code; inst != NULL; inst = inst->next) {
738 if (FOLLOW_ALIAS_ANALYSIS) {
739 printf ("TRAVERSING INST: ");
740 mono_print_tree_nl (inst);
742 update_aliasing_information_on_inst (info, bb_info, inst, NULL);
745 g_assert (info->number_of_arguments == 0);
750 for (i = 0; i < cfg->num_bblocks; i++) {
751 MonoAliasingInformationInBB *bb_info = &(info->bb [i]);
752 MonoAliasUsageInformation *use;
754 for (use = bb_info->potential_alias_uses; use != NULL; use = use->next) {
755 if ((use->affected_variables != NULL) && (use->affected_variables->variable_index == NO_VARIABLE_INDEX)) {
756 if (use->affected_variables->next == NULL) {
757 use->affected_variables = info->uncontrollably_aliased_variables;
759 MonoLocalVariableList *last = use->affected_variables;
760 while (last->next != NULL) {
761 while (last->next && info->variable_is_uncontrollably_aliased [last->next->variable_index]) {
762 last->next = last->next->next;
764 if (last->next != NULL) {
768 if (last->variable_index != NO_VARIABLE_INDEX) {
769 use->affected_variables = use->affected_variables->next;
770 last->next = info->uncontrollably_aliased_variables;
772 use->affected_variables = info->uncontrollably_aliased_variables;
780 if (DUMP_ALIAS_ANALYSIS) {
781 print_code_with_aliasing_information (info);
784 #if (DEBUG_ALIAS_ANALYSIS)
785 cfg->verbose_level = verbose_level;
793 mono_destroy_aliasing_information (MonoAliasingInformation *info) {
794 mono_mempool_destroy (info->mempool);
798 mono_aliasing_initialize_code_traversal (MonoAliasingInformation *info, MonoBasicBlock *bb) {
799 info->next_interesting_inst = info->bb [bb->dfn].potential_alias_uses;
802 MonoLocalVariableList*
803 mono_aliasing_get_affected_variables_for_inst_traversing_code (MonoAliasingInformation *info, MonoInst *inst) {
804 if ((inst->ssa_op == MONO_SSA_LOAD) || (inst->ssa_op == MONO_SSA_STORE)) {
805 return &(info->variables [inst->inst_i0->inst_c0]);
806 } else if (info->next_interesting_inst != NULL) {
807 if (inst == info->next_interesting_inst->inst) {
808 MonoLocalVariableList *result = info->next_interesting_inst->affected_variables;
809 info->next_interesting_inst = info->next_interesting_inst->next;
811 } else if (inst->ssa_op != MONO_SSA_NOP) {
812 if (inst->ssa_op == MONO_SSA_ADDRESS_TAKEN) {
815 printf ("ERROR: instruction not found '");
816 //print_tree_with_aliasing_information (info, inst);
817 mono_print_tree (inst);
819 //g_assert_not_reached ();
831 static MonoLocalVariableList*
832 mono_aliasing_get_affected_variables_for_inst_in_bb (MonoAliasingInformation *info, MonoInst *inst, MonoBasicBlock *bb) {
833 MonoAliasUsageInformation *use;
835 for (use = info->bb [bb->dfn].potential_alias_uses; use != NULL; use = use->next) {
836 if (use->inst == inst) {
837 return use->affected_variables;
840 g_assert_not_reached ();
845 MonoLocalVariableList*
846 mono_aliasing_get_affected_variables_for_inst (MonoAliasingInformation *info, MonoInst *inst) {
849 for (i = 0; i < info->cfg->num_bblocks; i++) {
850 MonoAliasingInformationInBB *bb_info = &(info->bb [i]);
851 MonoAliasUsageInformation *use;
853 for (use = info->bb [bb_info->bb->dfn].potential_alias_uses; use != NULL; use = use->next) {
854 if (use->inst == inst) {
855 return use->affected_variables;
859 g_assert_not_reached ();
863 #if (MONO_APPLY_DEADCE_TO_SINGLE_METHOD)
865 mono_deadce_method_name = NULL;
866 static gboolean check_deadce_method_name (MonoCompile *cfg) {
868 if (mono_deadce_method_name == NULL) {
869 mono_deadce_method_name = getenv ("MONO_DEADCE_METHOD_NAME");
871 if (mono_deadce_method_name != NULL) {
872 char *method_name = mono_method_full_name (cfg->method, TRUE);
873 if (strstr (method_name, mono_deadce_method_name) != NULL) {
878 g_free (method_name);
889 #define LOG_DEADCE (info->cfg->verbose_level > 0)
891 #define LOG_DEADCE (info->cfg->verbose_level > 4)
895 mono_aliasing_deadce_on_inst (MonoAliasingInformation *info, MonoInst **possibly_dead_assignments, MonoInst *inst) {
897 gboolean has_side_effects;
898 MonoLocalVariableList *affected_variables;
900 arity = mono_burg_arity [inst->opcode];
902 switch (inst->opcode) {
903 #define OPDEF(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) case a1:
904 #include "simple-cee-ops.h"
906 #define MINI_OP(a1,a2) case a1:
907 #include "simple-mini-ops.h"
909 has_side_effects = FALSE;
912 has_side_effects = TRUE;
916 if (mono_aliasing_deadce_on_inst (info, possibly_dead_assignments, inst->inst_i0)) {
917 has_side_effects = TRUE;
920 if (mono_aliasing_deadce_on_inst (info, possibly_dead_assignments, inst->inst_i1)) {
921 has_side_effects = TRUE;
927 affected_variables = mono_aliasing_get_affected_variables_for_inst_traversing_code (info, inst);
929 if (affected_variables != NULL) {
930 if (inst->ssa_op & MONO_SSA_LOAD) {
931 MonoLocalVariableList *affected_variable;
932 for (affected_variable = affected_variables; affected_variable != NULL; affected_variable = affected_variable->next) {
934 printf ("CLEARING slot %d at inst ", affected_variable->variable_index);
935 mono_print_tree_nl (inst);
937 possibly_dead_assignments [affected_variable->variable_index] = NULL;
940 if (inst->ssa_op & MONO_SSA_STORE) {
941 MonoLocalVariableList *affected_variable;
942 for (affected_variable = affected_variables; affected_variable != NULL; affected_variable = affected_variable->next) {
943 if (possibly_dead_assignments [affected_variable->variable_index] != NULL) {
945 printf ("KILLING slot %d at inst ", affected_variable->variable_index);
946 mono_print_tree_nl (inst);
948 possibly_dead_assignments [affected_variable->variable_index]->opcode = OP_NOP;
949 possibly_dead_assignments [affected_variable->variable_index]->ssa_op = MONO_SSA_NOP;
950 possibly_dead_assignments [affected_variable->variable_index] = NULL;
954 //printf ("FAST DEADCE TOTAL LOCAL\n");
959 if ((! has_side_effects) && (inst->ssa_op == MONO_SSA_STORE)) {
961 printf ("FILLING slot %d with inst ", (int)inst->inst_i0->inst_c0);
962 mono_print_tree_nl (inst);
964 possibly_dead_assignments [inst->inst_i0->inst_c0] = inst;
967 return has_side_effects;
972 mono_aliasing_deadce (MonoAliasingInformation *info) {
974 MonoInst **possibly_dead_assignments;
979 possibly_dead_assignments = alloca (cfg->num_varinfo * sizeof (MonoInst*));
982 printf ("BEFORE DEADCE START\n");
983 mono_print_code (cfg);
984 printf ("BEFORE DEADCE END\n");
987 #if (MONO_APPLY_DEADCE_TO_SINGLE_METHOD)
988 if (! check_deadce_method_name (cfg)) {
990 printf ("DEADCE disabled setting MONO_DEADCE_METHOD_NAME\n");
996 for (i = 0; i < cfg->num_bblocks; i++) {
1001 bb = cfg->bblocks [i];
1002 memset (possibly_dead_assignments, 0, cfg->num_varinfo * sizeof (MonoInst*));
1003 mono_aliasing_initialize_code_traversal (info, bb);
1006 printf ("Working on BB %d\n", bb->block_num);
1009 for (inst = bb->code; inst != NULL; inst = inst->next) {
1010 mono_aliasing_deadce_on_inst (info, possibly_dead_assignments, inst);
1011 if (inst->opcode == OP_JMP) {
1012 /* Keep arguments live! */
1013 for (variable_index = 0; variable_index < cfg->num_varinfo; variable_index++) {
1014 if (cfg->varinfo [variable_index]->opcode == OP_ARG) {
1016 printf ("FINALLY CLEARING slot %d (JMP), inst was ", variable_index);
1017 mono_print_tree_nl (possibly_dead_assignments [variable_index]);
1019 possibly_dead_assignments [variable_index] = NULL;
1025 for (variable_index = 0; variable_index < cfg->num_varinfo; variable_index++) {
1026 if ((possibly_dead_assignments [variable_index] != NULL) && (! mono_bitset_test (bb->live_out_set, variable_index))) {
1028 printf ("FINALLY KILLING slot %d, inst was ", variable_index);
1029 mono_print_tree_nl (possibly_dead_assignments [variable_index]);
1032 //printf ("FAST DEADCE DEAD LOCAL\n");
1034 possibly_dead_assignments [variable_index]->opcode = OP_NOP;
1035 possibly_dead_assignments [variable_index]->ssa_op = MONO_SSA_NOP;
1041 printf ("AFTER DEADCE START\n");
1042 mono_print_code (cfg);
1043 printf ("AFTER DEADCE END\n");