Moved ProviderCollectionTest.cs from System assembly to System.Configuration.
[mono.git] / mono / mini / aliasing.c
1 /*
2  * aliasing.c: Alias Analysis
3  *
4  * Author:
5  *   Massimiliano Mantione (massi@ximian.com)
6  *
7  * (C) 2005 Novell, Inc.  http://www.novell.com
8  */
9 #include <string.h>
10 #include <stdio.h>
11
12 #include <mono/metadata/debug-helpers.h>
13 #include <mono/metadata/mempool.h>
14 #include <mono/metadata/opcodes.h>
15
16 #include "aliasing.h"
17
18 #define MONO_APPLY_DEADCE_TO_SINGLE_METHOD 0
19 #define DEBUG_DEADCE 0
20
21 #define DEBUG_ALIAS_ANALYSIS 0
22
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)
26
27 static const char *mono_aliasing_value_names[] = {
28         "ANY",
29         "NO_ALIAS",
30         "LOCAL",
31         "LOCAL_FIELD"
32 };
33
34
35 static const char *mono_stack_type_names[] = {
36         "STACK_INV",
37         "STACK_I4",
38         "STACK_I8",
39         "STACK_PTR",
40         "STACK_R8",
41         "STACK_MP",
42         "STACK_OBJ",
43         "STACK_VTYPE",
44         "STACK_MAX"
45 };
46
47 #define NO_VARIABLE_INDEX MONO_ALIASING_INVALID_VARIABLE_INDEX
48
49
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)==OP_CALL)||((op)==OP_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)))
66
67
68 /*
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).
73  */
74 typedef struct MonoAliasingInformationContext {
75         MonoInst *inst;
76         int current_subtree;
77         MonoAliasValue subtree_aliases [2];
78         
79         struct MonoAliasingInformationContext *father;
80 } MonoAliasingInformationContext;
81
82
83 static void
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);
88         } else {
89                 printf ("]");
90         }
91 }
92
93 static void
94 print_ssaop_value (int ssaop_value) {
95         printf ("[");
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 (".");
99         printf ("]");
100 }
101
102 static void
103 print_aliasing_context (MonoAliasingInformationContext *context) {
104         printf ("CONTEXT: left ");
105         print_alias_value (&(context->subtree_aliases [0]));
106         printf (", right ");
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]));
111         }
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);
115                 printf (" ");
116         }
117         printf ("in inst ");
118         mono_print_tree_nl (context->inst);
119 }
120
121 static void
122 print_tree_node (MonoInst *tree) {
123         if (!tree)
124                 return;
125         
126         printf (mono_inst_name (tree->opcode));
127         
128         if (OP_IS_OUTARG (tree->opcode)) {
129                 printf ("[OUT:%ld]", (long)tree->inst_c1);
130         }
131         
132         switch (tree->opcode) {
133         case OP_ICONST:
134                 printf ("[%d]", (int)tree->inst_c0);
135                 break;
136         case OP_I8CONST:
137                 printf ("[%lld]", (long long)tree->inst_l);
138                 break;
139         case OP_R8CONST:
140                 printf ("[%f]", *(double*)tree->inst_p0);
141                 break;
142         case OP_R4CONST:
143                 printf ("[%f]", *(float*)tree->inst_p0);
144                 break;
145         case OP_ARG:
146         case OP_LOCAL:
147                 printf ("[%d]", (int)tree->inst_c0);
148                 break;
149         case OP_REGOFFSET:
150                 if (tree->inst_offset < 0)
151                         printf ("[-0x%x(%s)]", (int)(-tree->inst_offset), mono_arch_regname (tree->inst_basereg));
152                 else
153                         printf ("[0x%x(%s)]", (int)(tree->inst_offset), mono_arch_regname (tree->inst_basereg));
154                 break;
155         case OP_REGVAR:
156                 printf ("[%s]", mono_arch_regname (tree->dreg));
157                 break;
158         case CEE_NEWARR:
159                 printf ("[%s]",  tree->inst_newa_class->name);
160                 break;
161         case OP_CALL:
162         case OP_CALLVIRT:
163         case OP_FCALL:
164         case OP_FCALLVIRT:
165         case OP_LCALL:
166         case OP_LCALLVIRT:
167         case OP_VCALL:
168         case OP_VCALLVIRT:
169         case OP_VOIDCALL:
170         case OP_VOIDCALLVIRT:
171         case OP_TRAMPCALL_VTABLE:
172         case OP_CALL_RGCTX:
173         case OP_FCALL_RGCTX:
174         case OP_VOIDCALL_RGCTX:
175         case OP_LCALL_RGCTX:
176         case OP_VCALL_RGCTX:
177         case OP_CALL_REG_RGCTX:
178         case OP_FCALL_REG_RGCTX:
179         case OP_VOIDCALL_REG_RGCTX:
180         case OP_LCALL_REG_RGCTX:
181         case OP_VCALL_REG_RGCTX:
182         case OP_CALLVIRT_IMT:
183         case OP_VOIDCALLVIRT_IMT:
184         case OP_FCALLVIRT_IMT:
185         case OP_LCALLVIRT_IMT:
186         case OP_VCALLVIRT_IMT: {
187                 MonoCallInst *call = (MonoCallInst*)tree;
188                 if (call->method)
189                         printf ("[%s]", call->method->name);
190                 else if (call->fptr) {
191                         MonoJitICallInfo *info = mono_find_jit_icall_by_addr (call->fptr);
192                         if (info)
193                                 printf ("[%s]", info->name);
194                 }
195                 printf ("[ARGS:%d]", call->signature->param_count);
196                 break;
197         }
198         case OP_PHI: {
199                 int i;
200                 printf ("[%d (", (int)tree->inst_c0);
201                 for (i = 0; i < tree->inst_phi_args [0]; i++) {
202                         if (i)
203                                 printf (", ");
204                         printf ("%d", tree->inst_phi_args [i + 1]);
205                 }
206                 printf (")]");
207                 break;
208         }
209         case OP_LOAD_MEMBASE:
210         case OP_LOADI4_MEMBASE:
211         case OP_LOADU4_MEMBASE:
212         case OP_LOADU1_MEMBASE:
213         case OP_LOADI1_MEMBASE:
214         case OP_LOADU2_MEMBASE:
215         case OP_LOADI2_MEMBASE:
216                 printf ("[%s] <- [%s + 0x%x]", mono_arch_regname (tree->dreg), mono_arch_regname (tree->inst_basereg), (int)tree->inst_offset);
217                 break;
218         case OP_BR:
219         case OP_CALL_HANDLER:
220                 printf ("[B%d]", tree->inst_target_bb->block_num);
221                 break;
222         case CEE_BNE_UN:
223         case CEE_BEQ:
224         case CEE_BLT:
225         case CEE_BLT_UN:
226         case CEE_BGT:
227         case CEE_BGT_UN:
228         case CEE_BGE:
229         case CEE_BGE_UN:
230         case CEE_BLE:
231         case CEE_BLE_UN:
232                 printf ("[B%dB%d]", tree->inst_true_bb->block_num, tree->inst_false_bb->block_num);
233                 break;
234         case OP_DUMMY_USE:
235                 printf ("[%d]", (int)tree->inst_i0->inst_i0->inst_c0);
236                 break;
237         case OP_DUMMY_STORE:
238                 printf ("[%d]", (int)tree->inst_i0->inst_c0);
239                 break;
240         default:
241                 break;
242         }
243 }
244
245 static void
246 print_variable_list (MonoLocalVariableList* variables) {
247         printf ("{");
248         while (variables != NULL) {
249                 printf ("%d", variables->variable_index);
250                 if (variables->next != NULL) {
251                         printf (",");
252                 }
253                 variables = variables->next;
254         }
255         printf ("}");
256 }
257
258 static void
259 print_used_aliases(MonoInst *inst, MonoLocalVariableList* affected_variables) {
260         if (inst->ssa_op != MONO_SSA_NOP) {
261                 printf (" <");
262                 if (inst->ssa_op & MONO_SSA_ADDRESS_TAKEN) printf ("I");
263                 if (inst->ssa_op & MONO_SSA_LOAD) printf ("R");
264                 if (inst->ssa_op & MONO_SSA_STORE) printf ("W");
265                 if (inst->ssa_op != MONO_SSA_ADDRESS_TAKEN) {
266                         print_variable_list (affected_variables);
267                 } else {
268                         switch (inst->inst_i0->opcode) {
269                         case OP_LOCAL:
270                         case OP_ARG:
271                                 printf ("{%ld}", (long)inst->inst_i0->inst_c0);
272                                 break;
273                         case OP_RETARG:
274                                 printf ("{RETARG}");
275                                 break;
276                         default:
277                                 printf ("{ANY}");
278                                 break;
279                         }
280                 }
281                 printf (">");
282         }
283 }
284
285 static void
286 print_tree_with_aliasing_information (MonoAliasingInformation *info, MonoInst *tree) {
287         int arity;
288         MonoLocalVariableList* affected_variables;
289
290         if (!tree) {
291                 printf ("NULL-INST");
292                 return;
293         }
294         
295         arity = mono_burg_arity [tree->opcode];
296         
297         print_tree_node (tree);
298         
299         if (OP_IS_CALL (tree->opcode) && arity) {
300                 printf (" THIS:");
301         }
302         
303         if (arity) {
304                 printf (" (");
305                 print_tree_with_aliasing_information (info, tree->inst_i0);
306                 if (arity > 1) {
307                         printf (" ");
308                         print_tree_with_aliasing_information (info, tree->inst_i1);
309                 }
310                 printf (")");
311         }
312         
313         affected_variables = mono_aliasing_get_affected_variables_for_inst_traversing_code (info, tree);
314         print_used_aliases (tree, affected_variables);
315 }
316
317 static void
318 print_code_with_aliasing_information (MonoAliasingInformation *info) {
319         char *name = mono_method_full_name (info->cfg->method, TRUE);
320         int i;
321         
322         printf ("ALIASING DATA START (METHOD %s)\n", name);
323         printf ("ALIASED VARIABLES: ");
324         print_variable_list (info->uncontrollably_aliased_variables);
325         printf ("\n");
326         for (i = 0; i < info->cfg->num_bblocks; i++) {
327                 MonoAliasingInformationInBB *bb_info = &(info->bb [i]);
328                 MonoAliasUsageInformation *use;
329                 MonoInst *inst;
330                 
331                 printf ("CODE FOR BB %d\n", bb_info->bb->block_num);
332                 mono_aliasing_initialize_code_traversal (info, bb_info->bb);
333                 MONO_BB_FOR_EACH_INS (bb_info->bb, inst) {
334                         print_tree_with_aliasing_information (info, inst);
335                         printf ("\n");
336                 }
337                 
338                 printf ("USES FOR BB %d\n", bb_info->bb->block_num);
339                 for (use = bb_info->potential_alias_uses; use != NULL; use = use->next) {
340                         mono_print_tree (use->inst);
341                         print_used_aliases (use->inst, use->affected_variables);
342                         printf ("\n");
343                 }               
344         }
345         printf ("ALIASING DATA END (METHOD %s)\n", name);
346         g_free (name);
347 }       
348
349
350 #define APPEND_USE(info,bb_info,use) do {\
351                 (use)->next = NULL;\
352                 if ((info)->next_interesting_inst != NULL) {\
353                         (info)->next_interesting_inst->next = (use);\
354                 } else {\
355                         (bb_info)->potential_alias_uses = (use);\
356                 }\
357                 (info)->next_interesting_inst = (use);\
358         } while (0)
359         
360 #define ADD_BAD_ALIAS(info,vi) do {\
361                 if (FOLLOW_ALIAS_ANALYSIS) {\
362                         printf ("ADDING BAD ALIAS FOR VARIABLE %d\n", vi);\
363                 }\
364                 if (! ((info)->variable_is_uncontrollably_aliased [(vi)])) {\
365                         MonoLocalVariableList *variable = mono_mempool_alloc ((info)->mempool, sizeof (MonoLocalVariableList));\
366                         variable->variable_index = (vi);\
367                         variable->next = (info)->uncontrollably_aliased_variables;\
368                         (info)->uncontrollably_aliased_variables = variable;\
369                         (info)->variable_is_uncontrollably_aliased [(vi)] = TRUE;\
370                 }\
371         } while (0)
372
373 #define ADD_ARGUMGENT(info,inst,alias) do {\
374                 if ((info)->number_of_arguments == (info)->arguments_capacity) {\
375                         MonoInst **new_arguments = mono_mempool_alloc ((info)->mempool, sizeof (MonoInst*) * ((info)->arguments_capacity * 2));\
376                         MonoAliasValue *new_arguments_aliases = mono_mempool_alloc ((info)->mempool, sizeof (MonoAliasValue) * ((info)->arguments_capacity * 2));\
377                         memcpy (new_arguments, (info)->arguments, sizeof (MonoInst*) * ((info)->arguments_capacity));\
378                         memcpy (new_arguments_aliases, (info)->arguments_aliases, sizeof (MonoAliasValue) * ((info)->arguments_capacity));\
379                         (info)->arguments = new_arguments;\
380                         (info)->arguments_aliases = new_arguments_aliases;\
381                         (info)->arguments_capacity = (info)->arguments_capacity * 2;\
382                 }\
383                 (info)->arguments [(info)->number_of_arguments] = (inst);\
384                 (info)->arguments_aliases [(info)->number_of_arguments] = (alias);\
385                 (info)->number_of_arguments ++;\
386         } while (0)
387
388 #define ADD_UNIQUE_VARIABLE(info,list,vi) do {\
389                 MonoLocalVariableList* target_element = (list);\
390                 while ((target_element != NULL) && (target_element->variable_index != (vi))) {\
391                         target_element = target_element->next;\
392                 }\
393                 if (target_element == NULL) {\
394                         target_element = mono_mempool_alloc ((info)->mempool, sizeof (MonoLocalVariableList));\
395                         target_element->variable_index = (vi);\
396                         target_element->next = (list);\
397                         (list) = target_element;\
398                 }\
399         } while (0)
400
401 static void
402 update_aliasing_information_on_inst (MonoAliasingInformation *info, MonoAliasingInformationInBB *bb_info, MonoInst *inst, MonoAliasingInformationContext *father_context) {
403         MonoAliasingInformationContext context;
404         MonoAliasValue *father_alias;
405         
406         context.inst = inst;
407         context.father = father_context;
408         if (father_context != NULL) {
409                 father_alias = &(father_context->subtree_aliases [father_context->current_subtree]);
410         } else {
411                 father_alias = NULL;
412         }
413         
414         if (mono_burg_arity [inst->opcode]) {
415                 context.current_subtree = 0;
416                 context.subtree_aliases [0].type = MONO_ALIASING_TYPE_ANY;
417                 context.subtree_aliases [0].variable_index = NO_VARIABLE_INDEX;
418                 update_aliasing_information_on_inst (info, bb_info, inst->inst_i0, &context);
419                 
420                 if (mono_burg_arity [inst->opcode] > 1) {
421                         context.current_subtree = 1;
422                         context.subtree_aliases [1].type = MONO_ALIASING_TYPE_ANY;
423                         context.subtree_aliases [1].variable_index = NO_VARIABLE_INDEX;
424                         update_aliasing_information_on_inst (info, bb_info, inst->inst_i1, &context);
425                 } else {
426                         context.subtree_aliases [1].type = MONO_ALIASING_TYPE_NO_ALIAS;
427                 }
428         } else {
429                 context.subtree_aliases [0].type = MONO_ALIASING_TYPE_NO_ALIAS;
430                 context.subtree_aliases [1].type = MONO_ALIASING_TYPE_NO_ALIAS;
431         }
432         
433         if (OP_IS_CONST (inst->opcode)) {
434                 father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
435         } else if (inst->ssa_op == MONO_SSA_ADDRESS_TAKEN) {
436                 MonoInst *local = inst->inst_i0;
437                 if ((local->opcode == OP_LOCAL) || (local->opcode == OP_ARG)) {
438                         gssize variable_index = local->inst_c0;
439                         father_alias->type = MONO_ALIASING_TYPE_LOCAL;
440                         father_alias->variable_index = variable_index;
441                 } else if (local->opcode == OP_RETARG) {
442                         father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
443                 } else {
444                         father_alias->type = MONO_ALIASING_TYPE_ANY;
445                 }
446         } else if (inst->ssa_op == MONO_SSA_LOAD) {
447                 MonoInst *local = inst->inst_i0;
448                 
449                 if (LOAD_OF_LOCAL_GIVES_POINTER (inst,local)) {
450                         father_alias->type = MONO_ALIASING_TYPE_ANY;
451                 } else {
452                         father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
453                 }
454         } else if (OP_IS_LOAD (inst->opcode) || (inst->opcode == CEE_LDOBJ)) {
455                 MonoInst *address = inst->inst_i0;
456                 MonoLocalVariableList *affected_variables = NULL;
457                 
458                 if ((address->opcode == OP_LOCAL) || (address->opcode == OP_ARG)) {
459                         gssize variable_index = address->inst_c0;
460                         MonoInst *local = info->cfg->varinfo [variable_index];
461                         
462                         affected_variables = &(info->variables [variable_index]);
463                         if (LOAD_OF_LOCAL_GIVES_POINTER (inst,local)) {
464                                 father_alias->type = MONO_ALIASING_TYPE_ANY;
465                         } else {
466                                 father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
467                         }
468                 } else if (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL) {
469                         gssize variable_index = context.subtree_aliases [0].variable_index;
470                         MonoInst *local = info->cfg->varinfo [variable_index];
471                         
472                         affected_variables = &(info->variables [variable_index]);;
473                         if (LOAD_OF_LOCAL_GIVES_POINTER (inst,local)) {
474                                 father_alias->type = MONO_ALIASING_TYPE_ANY;
475                         } else {
476                                 father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
477                         }
478                 } else if (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL_FIELD) {
479                         gssize variable_index = context.subtree_aliases [0].variable_index;
480                         
481                         affected_variables = &(info->variables [variable_index]);;
482                         if (inst->type == STACK_MP) {
483                                 father_alias->type = MONO_ALIASING_TYPE_ANY;
484                         } else {
485                                 father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
486                         }
487                 } else {
488                         if (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_ANY) {
489                                 affected_variables = info->temporary_uncontrollably_aliased_variables;
490                         }
491                         if ((inst->type == STACK_MP) && (inst->inst_i0->opcode != OP_OBJADDR)) {
492                                 father_alias->type = MONO_ALIASING_TYPE_ANY;
493                         } else {
494                                 father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
495                         }
496                 }
497                 
498                 if (affected_variables != NULL) {
499                         MonoAliasUsageInformation *use = mono_mempool_alloc (info->mempool, sizeof (MonoAliasUsageInformation));
500                         
501                         inst->ssa_op = MONO_SSA_INDIRECT_LOAD;
502                         use->inst = inst;
503                         use->affected_variables = affected_variables;
504                         APPEND_USE (info,bb_info,use);
505                 }
506         } else if (inst->ssa_op == MONO_SSA_STORE) {
507                 if (context.subtree_aliases [1].type == MONO_ALIASING_TYPE_LOCAL) {
508                         ADD_BAD_ALIAS (info, context.subtree_aliases [1].variable_index);
509                 }
510         } else if (OP_IS_STORE (inst->opcode) || (inst->opcode == CEE_STOBJ)) {
511                 MonoInst *address = inst->inst_i0;
512                 MonoLocalVariableList *affected_variables = NULL;
513                 
514                 if (context.subtree_aliases [1].type == MONO_ALIASING_TYPE_LOCAL) {
515                         ADD_BAD_ALIAS (info, context.subtree_aliases [1].variable_index);
516                 }
517                 
518                 if ((address->opcode == OP_LOCAL) || (address->opcode == OP_ARG)) {
519                         gssize variable_index = address->inst_c0;
520                         
521                         affected_variables = &(info->variables [variable_index]);
522                 } else if ((context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL) || (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL_FIELD)) {
523                         gssize variable_index = context.subtree_aliases [0].variable_index;
524                         
525                         affected_variables = &(info->variables [variable_index]);;
526                 } else if (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_ANY) {
527                         affected_variables = info->temporary_uncontrollably_aliased_variables;
528                 }
529                 
530                 if (affected_variables != NULL) {
531                         MonoAliasUsageInformation *use = mono_mempool_alloc (info->mempool, sizeof (MonoAliasUsageInformation));
532                         
533                         inst->ssa_op = MONO_SSA_INDIRECT_STORE;
534                         use->inst = inst;
535                         use->affected_variables = affected_variables;
536                         APPEND_USE (info,bb_info,use);
537                 }
538         } else if (OP_IS_OUTARG (inst->opcode)) {
539                 ADD_ARGUMGENT (info,inst,context.subtree_aliases [0]);
540         } else if (OP_IS_CALL (inst->opcode)) {
541                 MonoCallInst *call = (MonoCallInst *) inst;
542                 MonoMethodSignature *sig = call->signature;
543                 gboolean call_has_untracked_pointer_argument = FALSE;
544                 MonoLocalVariableList *alias_arguments = NULL;
545                 int i;
546                 
547                 if ((context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL) || (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL_FIELD)) {
548                         ADD_UNIQUE_VARIABLE (info,alias_arguments,context.subtree_aliases [0].variable_index);
549                 } else if (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_ANY) {
550                         call_has_untracked_pointer_argument = TRUE;
551                 }
552                 
553                 if (FOLLOW_ALIAS_ANALYSIS) {
554                         printf ("CALL, scanning %d arguments\n", info->number_of_arguments);
555                 }
556                 for (i = 0; i < info->number_of_arguments; i++) {
557                         //FIXME
558                         //MonoInst *argument = info->arguments [i];
559                         MonoAliasValue arguments_alias = info->arguments_aliases [i];
560                         
561                         if ((arguments_alias.type == MONO_ALIASING_TYPE_LOCAL) || (arguments_alias.type == MONO_ALIASING_TYPE_LOCAL_FIELD)) {
562                                 if (FOLLOW_ALIAS_ANALYSIS) {
563                                         printf ("CALL, argument %d passes the address of local %d\n", i, arguments_alias.variable_index);
564                                 }
565                                 ADD_UNIQUE_VARIABLE (info,alias_arguments,arguments_alias.variable_index);
566                                 //FIXME
567                                 #if 0
568                                 if (((arguments_alias.type == MONO_ALIASING_TYPE_LOCAL)) && (argument->inst_c1 > 0)) {
569                                         int argument_index = argument->inst_c1 - 1;
570                                         if (argument_index < sig->param_count) {
571                                                 if (! (sig->params [argument_index]->byref)) {
572                                                         ADD_BAD_ALIAS (info, arguments_alias.variable_index);
573                                                 }
574                                         } else {
575                                                 printf ("*** ERROR: argument %d of %d: ", argument_index, sig->param_count);
576                                                 mono_print_tree_nl (argument);
577                                         }
578                                 }
579                                 #endif
580                         } else if (arguments_alias.type == MONO_ALIASING_TYPE_ANY) {
581                                 if (FOLLOW_ALIAS_ANALYSIS) {
582                                         printf ("CALL, argument %d could pass the address of any local\n", i);
583                                 }
584                                 call_has_untracked_pointer_argument = TRUE;
585                         }
586                         //FIXME
587                         #if 0
588                         else if (argument->inst_c1 > 0) {
589                                 int argument_index = argument->inst_c1 - 1;
590                                 if (argument_index < sig->param_count) {
591                                         if (sig->params [argument_index]->type == MONO_TYPE_PTR) {
592                                                 call_has_untracked_pointer_argument = TRUE;
593                                         }
594                                 } else {
595                                         printf ("*** ERROR: argument %d of %d: ", argument_index, sig->param_count);
596                                         mono_print_tree_nl (argument);
597                                 }
598                         }
599                         #endif
600                 }
601                 
602                 if ((alias_arguments != NULL) || call_has_untracked_pointer_argument) {
603                         MonoAliasUsageInformation *use = mono_mempool_alloc (info->mempool, sizeof (MonoAliasUsageInformation));
604                         
605                         inst->ssa_op = MONO_SSA_INDIRECT_LOAD_STORE;
606                         use->inst = inst;
607                         use->affected_variables = alias_arguments;
608                         if (call_has_untracked_pointer_argument) {
609                                 MonoLocalVariableList *untracked_element  = mono_mempool_alloc ((info)->mempool, sizeof (MonoLocalVariableList));
610                                 untracked_element->variable_index = NO_VARIABLE_INDEX;
611                                 untracked_element->next = use->affected_variables;
612                                 use->affected_variables = untracked_element;
613                         }
614                         APPEND_USE (info,bb_info,use);
615                 }
616                 
617                 if ((sig->ret != NULL) && (father_alias != NULL)) {
618                         if (sig->ret->type != MONO_TYPE_PTR) {
619                                 father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
620                         } else {
621                                 father_alias->type = MONO_ALIASING_TYPE_ANY;
622                         }
623                 }
624                 
625                 info->number_of_arguments = 0;
626         } else if ((inst->opcode == CEE_ADD) || (inst->opcode == OP_LADD)){
627                 if ((context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL) || (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL_FIELD)) {
628                         int variable_index = context.subtree_aliases [0].variable_index;
629                         //ADD_BAD_ALIAS (info, variable_index);
630                         father_alias->type = MONO_ALIASING_TYPE_LOCAL_FIELD;
631                         father_alias->variable_index = variable_index;
632                 } else if ((context.subtree_aliases [1].type == MONO_ALIASING_TYPE_LOCAL) || (context.subtree_aliases [1].type == MONO_ALIASING_TYPE_LOCAL_FIELD)) {
633                         int variable_index = context.subtree_aliases [1].variable_index;
634                         //ADD_BAD_ALIAS (info, variable_index);
635                         father_alias->type = MONO_ALIASING_TYPE_LOCAL_FIELD;
636                         father_alias->variable_index = variable_index;
637                 } else if ((context.subtree_aliases [0].type == MONO_ALIASING_TYPE_ANY) || (context.subtree_aliases [1].type == MONO_ALIASING_TYPE_ANY)) {
638                         father_alias->type = MONO_ALIASING_TYPE_ANY;
639                 } else {
640                         father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
641                 }
642         } else if ((inst->opcode == OP_MEMCPY) || (inst->opcode == OP_MEMSET)) {
643                 if ((context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL) || (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL_FIELD)) {
644                         MonoAliasUsageInformation *use = mono_mempool_alloc (info->mempool, sizeof (MonoAliasUsageInformation));
645                         
646                         inst->ssa_op = MONO_SSA_INDIRECT_STORE;
647                         use->inst = inst;
648                         use->affected_variables = &(info->variables [context.subtree_aliases [0].variable_index]);
649                         APPEND_USE (info,bb_info,use);
650                 } else if (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_ANY) {
651                         MonoAliasUsageInformation *use = mono_mempool_alloc (info->mempool, sizeof (MonoAliasUsageInformation));
652                         
653                         inst->ssa_op = MONO_SSA_INDIRECT_STORE;
654                         use->inst = inst;
655                         use->affected_variables = info->temporary_uncontrollably_aliased_variables;
656                         APPEND_USE (info,bb_info,use);
657                 }
658         } else if ((inst->opcode == OP_UNBOXCAST) || OP_IS_PCONV (inst->opcode) || OP_IS_ICONV (inst->opcode)) {
659                 father_alias->type = context.subtree_aliases [0].type;
660                 father_alias->variable_index = context.subtree_aliases [0].variable_index;
661         } else if ((inst->opcode == CEE_LDELEMA) || (inst->opcode == OP_COMPARE) || (inst->opcode == OP_SWITCH)) {
662                 if (father_alias != NULL) {
663                         father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
664                 }
665         } else {
666                 MonoAliasType father_type = MONO_ALIASING_TYPE_NO_ALIAS;
667                 MonoLocalVariableList *affected_variables = NULL;
668                 
669                 if ((context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL) || (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL_FIELD)) {
670                         affected_variables = &(info->variables [context.subtree_aliases [0].variable_index]);
671                         ADD_BAD_ALIAS (info, context.subtree_aliases [0].variable_index);
672                 }
673                 if ((context.subtree_aliases [1].type == MONO_ALIASING_TYPE_LOCAL) || (context.subtree_aliases [1].type == MONO_ALIASING_TYPE_LOCAL_FIELD)) {
674                         if (affected_variables == NULL) {
675                                 affected_variables = &(info->variables [context.subtree_aliases [1].variable_index]);
676                         } else if (affected_variables->variable_index != context.subtree_aliases [1].variable_index) {
677                                 int previous_index = affected_variables->variable_index;
678                                 affected_variables = NULL;
679                                 ADD_UNIQUE_VARIABLE (info, affected_variables, previous_index);
680                                 ADD_UNIQUE_VARIABLE (info, affected_variables, context.subtree_aliases [1].variable_index);
681                         }
682                         ADD_BAD_ALIAS (info, context.subtree_aliases [1].variable_index);
683                 }
684                 
685                 if (affected_variables != NULL) {
686                         MonoAliasUsageInformation *use = mono_mempool_alloc (info->mempool, sizeof (MonoAliasUsageInformation));
687                         
688                         inst->ssa_op = MONO_SSA_INDIRECT_LOAD_STORE;
689                         use->inst = inst;
690                         use->affected_variables = affected_variables;
691                         APPEND_USE (info, bb_info, use);
692                 }
693                 
694                 if (father_alias != NULL) { 
695                         if ((context.subtree_aliases [0].type == MONO_ALIASING_TYPE_ANY) || (context.subtree_aliases [1].type == MONO_ALIASING_TYPE_ANY)) {
696                                 father_type = MONO_ALIASING_TYPE_ANY;
697                         }
698                         father_alias->type = father_type;
699                 }
700         }
701         
702         if (FOLLOW_ALIAS_ANALYSIS) {
703                 print_aliasing_context (&context);
704         }
705 }
706
707
708
709 /**
710  * mono_build_aliasing_information:
711  * @cfg: Control Flow Graph
712  *
713  * Builds the aliasing information in a cfg.
714  * After this has run, all MonoInst.ssa_op fields will be properly
715  * set (it will use the MONO_SSA_ADDRESS_TAKEN, MONO_SSA_LOAD and
716  * MONO_SSA_STORE values as a starting point).
717  */
718 MonoAliasingInformation*
719 mono_build_aliasing_information (MonoCompile *cfg) {
720         MonoMemPool *pool = mono_mempool_new ();
721         MonoAliasingInformation *info = mono_mempool_alloc (pool, sizeof (MonoAliasingInformation));
722         int i;
723 #if (DEBUG_ALIAS_ANALYSIS)
724         int verbose_level = cfg->verbose_level;
725         cfg->verbose_level = 7;
726 #endif
727         
728         info->mempool = pool;
729         info->cfg = cfg;
730         info->bb = mono_mempool_alloc (pool, sizeof (MonoAliasingInformationInBB) * cfg->num_bblocks);
731         info->uncontrollably_aliased_variables = NULL;
732         info->next_interesting_inst = NULL;
733         info->variables = mono_mempool_alloc (pool, sizeof (MonoLocalVariableList) * cfg->num_varinfo);
734         info->variable_is_uncontrollably_aliased = mono_mempool_alloc (pool, sizeof (gboolean) * cfg->num_varinfo);
735         for (i = 0; i < cfg->num_varinfo; i++) {
736                 info->variables [i].next = NULL;
737                 info->variables [i].variable_index = i;
738                 info->variable_is_uncontrollably_aliased [i] = FALSE;
739         }
740         info->temporary_uncontrollably_aliased_variables = mono_mempool_alloc (pool, sizeof (MonoLocalVariableList));
741         info->temporary_uncontrollably_aliased_variables->next = NULL;
742         info->temporary_uncontrollably_aliased_variables->variable_index = NO_VARIABLE_INDEX;
743         info->arguments = mono_mempool_alloc (pool, sizeof (MonoInst*) * 16);
744         info->arguments_aliases = mono_mempool_alloc (pool, sizeof (MonoAliasValue) * 16);
745         info->arguments_capacity = 16;
746         info->number_of_arguments = 0;
747         
748         for (i = 0; i < cfg->num_bblocks; i++) {
749                 MonoBasicBlock *bb = cfg->bblocks [i];
750                 MonoAliasingInformationInBB *bb_info = &(info->bb [i]);
751                 MonoInst *inst;
752                 
753                 if (FOLLOW_ALIAS_ANALYSIS) {
754                         printf ("TRAVERSING BB %d\n", bb->block_num);
755                 }
756                 
757                 bb_info->bb = bb;
758                 bb_info->potential_alias_uses = NULL;
759                 info->next_interesting_inst = NULL;
760                 
761                 MONO_BB_FOR_EACH_INS (bb, inst) {
762                         if (FOLLOW_ALIAS_ANALYSIS) {
763                                 printf ("TRAVERSING INST: ");
764                                 mono_print_tree_nl (inst);
765                         }
766                         update_aliasing_information_on_inst (info, bb_info, inst, NULL);
767                 }
768                 
769                 g_assert (info->number_of_arguments == 0);
770         }
771         
772         //FIXME
773         //#if 0
774         for (i = 0; i < cfg->num_bblocks; i++) {
775                 MonoAliasingInformationInBB *bb_info = &(info->bb [i]);
776                 MonoAliasUsageInformation *use;
777                 
778                 for (use = bb_info->potential_alias_uses; use != NULL; use = use->next) {
779                         if ((use->affected_variables != NULL) && (use->affected_variables->variable_index == NO_VARIABLE_INDEX)) {
780                                 if (use->affected_variables->next == NULL) {
781                                         use->affected_variables = info->uncontrollably_aliased_variables;
782                                 } else {
783                                         MonoLocalVariableList *last = use->affected_variables;
784                                         while (last->next != NULL) {
785                                                 while (last->next && info->variable_is_uncontrollably_aliased [last->next->variable_index]) {
786                                                         last->next = last->next->next;
787                                                 }
788                                                 if (last->next != NULL) {
789                                                         last = last->next;
790                                                 }
791                                         }
792                                         if (last->variable_index != NO_VARIABLE_INDEX) {
793                                                 use->affected_variables = use->affected_variables->next;
794                                                 last->next = info->uncontrollably_aliased_variables;
795                                         } else {
796                                                 use->affected_variables = info->uncontrollably_aliased_variables;
797                                         }
798                                 }
799                         }
800                 }
801         }
802         //#endif
803         
804         if (DUMP_ALIAS_ANALYSIS) {
805                 print_code_with_aliasing_information (info);
806         }
807         
808 #if (DEBUG_ALIAS_ANALYSIS)
809         cfg->verbose_level = verbose_level;
810 #endif
811         
812         return info;
813 }
814
815
816 void
817 mono_destroy_aliasing_information (MonoAliasingInformation *info) {
818         mono_mempool_destroy (info->mempool);
819 }
820
821 void
822 mono_aliasing_initialize_code_traversal (MonoAliasingInformation *info, MonoBasicBlock *bb) {
823         info->next_interesting_inst = info->bb [bb->dfn].potential_alias_uses;
824 }
825
826 MonoLocalVariableList*
827 mono_aliasing_get_affected_variables_for_inst_traversing_code (MonoAliasingInformation *info, MonoInst *inst) {
828         if ((inst->ssa_op == MONO_SSA_LOAD) || (inst->ssa_op == MONO_SSA_STORE)) {
829                 return &(info->variables [inst->inst_i0->inst_c0]);
830         } else if (info->next_interesting_inst != NULL) {
831                 if (inst == info->next_interesting_inst->inst) {
832                         MonoLocalVariableList *result = info->next_interesting_inst->affected_variables;
833                         info->next_interesting_inst = info->next_interesting_inst->next;
834                         return result;
835                 } else if (inst->ssa_op != MONO_SSA_NOP) {
836                         if (inst->ssa_op == MONO_SSA_ADDRESS_TAKEN) {
837                                 return NULL;
838                         } else {
839                                 printf ("ERROR: instruction not found '");
840                                 //print_tree_with_aliasing_information (info, inst);
841                                 mono_print_tree (inst);
842                                 printf ("'\n");
843                                 //g_assert_not_reached ();
844                                 return NULL;
845                         }
846                 } else {
847                         return NULL;
848                 }
849         } else {
850                 return NULL;
851         }
852 }
853
854 #if 0
855 static MonoLocalVariableList*
856 mono_aliasing_get_affected_variables_for_inst_in_bb (MonoAliasingInformation *info, MonoInst *inst, MonoBasicBlock *bb) {
857         MonoAliasUsageInformation *use;
858         
859         for (use = info->bb [bb->dfn].potential_alias_uses; use != NULL; use = use->next) {
860                 if (use->inst == inst) {
861                         return use->affected_variables;
862                 }
863         }
864         g_assert_not_reached ();
865         return NULL;
866 }
867 #endif
868
869 MonoLocalVariableList*
870 mono_aliasing_get_affected_variables_for_inst (MonoAliasingInformation *info, MonoInst *inst) {
871         int i;
872         
873         for (i = 0; i < info->cfg->num_bblocks; i++) {
874                 MonoAliasingInformationInBB *bb_info = &(info->bb [i]);
875                 MonoAliasUsageInformation *use;
876                 
877                 for (use = info->bb [bb_info->bb->dfn].potential_alias_uses; use != NULL; use = use->next) {
878                         if (use->inst == inst) {
879                                 return use->affected_variables;
880                         }
881                 }
882         }
883         g_assert_not_reached ();
884         return NULL;
885 }
886
887 #if (MONO_APPLY_DEADCE_TO_SINGLE_METHOD)
888 static char*
889 mono_deadce_method_name = NULL;
890 static gboolean check_deadce_method_name (MonoCompile *cfg) {
891         gboolean result;
892         if (mono_deadce_method_name == NULL) {
893                 mono_deadce_method_name = getenv ("MONO_DEADCE_METHOD_NAME");
894         }
895         if (mono_deadce_method_name != NULL) {
896                 char *method_name = mono_method_full_name (cfg->method, TRUE);
897                 if (strstr (method_name, mono_deadce_method_name) != NULL) {
898                         result = TRUE;
899                 } else {
900                         result = FALSE;
901                 }
902                 g_free (method_name);
903         } else {
904                 result = TRUE;
905         }
906         return result;
907 }
908 #endif
909
910
911
912 #if (DEBUG_DEADCE)
913 #define LOG_DEADCE (info->cfg->verbose_level > 0)
914 #else
915 #define LOG_DEADCE (info->cfg->verbose_level > 4)
916 #endif
917
918 static gboolean
919 mono_aliasing_deadce_on_inst (MonoAliasingInformation *info, MonoInst **possibly_dead_assignments, MonoInst *inst) {
920         int arity;
921         gboolean has_side_effects;
922         MonoLocalVariableList *affected_variables;
923         
924         arity = mono_burg_arity [inst->opcode];
925         
926         switch (inst->opcode) {
927 #define OPDEF(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) case a1:
928 #include "simple-cee-ops.h"
929 #undef OPDEF
930 #define MINI_OP(a1,a2) case a1:
931 #include "simple-mini-ops.h"
932 #undef MINI_OP
933                 has_side_effects = FALSE;
934                 break;
935         default:
936                 has_side_effects = TRUE;
937         }
938         
939         if (arity) {
940                 if (mono_aliasing_deadce_on_inst (info, possibly_dead_assignments, inst->inst_i0)) {
941                         has_side_effects = TRUE;
942                 }
943                 if (arity > 1) {
944                         if (mono_aliasing_deadce_on_inst (info, possibly_dead_assignments, inst->inst_i1)) {
945                                 has_side_effects = TRUE;
946                         }
947                         
948                 }
949         }
950         
951         affected_variables = mono_aliasing_get_affected_variables_for_inst_traversing_code (info, inst);
952         
953         if (affected_variables != NULL) {
954                 if (inst->ssa_op & MONO_SSA_LOAD) {
955                         MonoLocalVariableList *affected_variable;
956                         for (affected_variable = affected_variables; affected_variable != NULL; affected_variable = affected_variable->next) {
957                                 if (LOG_DEADCE) {
958                                         printf ("CLEARING slot %d at inst ", affected_variable->variable_index);
959                                         mono_print_tree_nl (inst);
960                                 }
961                                 possibly_dead_assignments [affected_variable->variable_index] = NULL;
962                         }
963                 }
964                 if (inst->ssa_op & MONO_SSA_STORE) {
965                         MonoLocalVariableList *affected_variable;
966                         for (affected_variable = affected_variables; affected_variable != NULL; affected_variable = affected_variable->next) {
967                                 if (possibly_dead_assignments [affected_variable->variable_index] != NULL) {
968                                         if (LOG_DEADCE) {
969                                                 printf ("KILLING slot %d at inst ", affected_variable->variable_index);
970                                                 mono_print_tree_nl (inst);
971                                         }
972                                         possibly_dead_assignments [affected_variable->variable_index]->opcode = OP_NOP;
973                                         possibly_dead_assignments [affected_variable->variable_index]->ssa_op = MONO_SSA_NOP;
974                                         possibly_dead_assignments [affected_variable->variable_index] = NULL;
975                                 }
976                         }
977                         
978                         //printf ("FAST DEADCE TOTAL LOCAL\n");
979                 }
980                 
981         }
982         
983         if ((! has_side_effects) && (inst->ssa_op == MONO_SSA_STORE)) {
984                 if (LOG_DEADCE) {
985                         printf ("FILLING slot %d with inst ", (int)inst->inst_i0->inst_c0);
986                         mono_print_tree_nl (inst);
987                 }
988                 possibly_dead_assignments [inst->inst_i0->inst_c0] = inst;
989         }
990         
991         return has_side_effects;
992 }
993
994
995 void
996 mono_aliasing_deadce (MonoAliasingInformation *info) {
997         MonoCompile *cfg;
998         MonoInst **possibly_dead_assignments;
999         int i;
1000                 
1001         cfg = info->cfg;
1002         
1003         possibly_dead_assignments = alloca (cfg->num_varinfo * sizeof (MonoInst*));
1004         
1005         if (LOG_DEADCE) {
1006                 mono_print_code (cfg, "BEFORE DEADCE START");
1007         }
1008         
1009 #if (MONO_APPLY_DEADCE_TO_SINGLE_METHOD)
1010         if (! check_deadce_method_name (cfg)) {
1011                 if (LOG_DEADCE) {
1012                         printf ("DEADCE disabled setting MONO_DEADCE_METHOD_NAME\n");
1013                 }
1014                 return;
1015         }
1016 #endif
1017         
1018         for (i = 0; i < cfg->num_bblocks; i++) {
1019                 MonoBasicBlock *bb;
1020                 MonoInst *inst;
1021                 int variable_index;
1022                 
1023                 bb = cfg->bblocks [i];
1024                 memset (possibly_dead_assignments, 0, cfg->num_varinfo * sizeof (MonoInst*));
1025                 mono_aliasing_initialize_code_traversal (info, bb);
1026                 
1027                 if (LOG_DEADCE) {
1028                         printf ("Working on BB %d\n", bb->block_num);
1029                 }
1030                 
1031                 MONO_BB_FOR_EACH_INS (bb, inst) {
1032                         mono_aliasing_deadce_on_inst (info, possibly_dead_assignments, inst);
1033                         if (inst->opcode == OP_JMP) {
1034                                 /* Keep arguments live! */
1035                                 for (variable_index = 0; variable_index < cfg->num_varinfo; variable_index++) {
1036                                         if (cfg->varinfo [variable_index]->opcode == OP_ARG) {
1037                                                 if (LOG_DEADCE) {
1038                                                         printf ("FINALLY CLEARING slot %d (JMP), inst was ", variable_index);
1039                                                         mono_print_tree_nl (possibly_dead_assignments [variable_index]);
1040                                                 }
1041                                                 possibly_dead_assignments [variable_index] = NULL;
1042                                         }
1043                                 }
1044                         }
1045                 }
1046                 
1047                 for (variable_index = 0; variable_index < cfg->num_varinfo; variable_index++) {
1048                         if ((possibly_dead_assignments [variable_index] != NULL) && (! mono_bitset_test (bb->live_out_set, variable_index))) {
1049                                 if (LOG_DEADCE) {
1050                                         printf ("FINALLY KILLING slot %d, inst was ", variable_index);
1051                                         mono_print_tree_nl (possibly_dead_assignments [variable_index]);
1052                                 }
1053                                 
1054                                 //printf ("FAST DEADCE DEAD LOCAL\n");
1055                                 
1056                                 possibly_dead_assignments [variable_index]->opcode = OP_NOP;
1057                                 possibly_dead_assignments [variable_index]->ssa_op = MONO_SSA_NOP;
1058                         }
1059                 }
1060         }
1061         
1062         if (LOG_DEADCE) {
1063                 mono_print_code (cfg, "AFTER DEADCE");
1064         }
1065 }