2007-12-07 Mark Probst <mark.probst@gmail.com>
[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)==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)))
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 CEE_CALL:
162         case CEE_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                 MonoCallInst *call = (MonoCallInst*)tree;
173                 if (call->method)
174                         printf ("[%s]", call->method->name);
175                 else if (call->fptr) {
176                         MonoJitICallInfo *info = mono_find_jit_icall_by_addr (call->fptr);
177                         if (info)
178                                 printf ("[%s]", info->name);
179                 }
180                 printf ("[ARGS:%d]", call->signature->param_count);
181                 break;
182         }
183         case OP_PHI: {
184                 int i;
185                 printf ("[%d (", (int)tree->inst_c0);
186                 for (i = 0; i < tree->inst_phi_args [0]; i++) {
187                         if (i)
188                                 printf (", ");
189                         printf ("%d", tree->inst_phi_args [i + 1]);
190                 }
191                 printf (")]");
192                 break;
193         }
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);
202                 break;
203         case OP_BR:
204         case OP_CALL_HANDLER:
205                 printf ("[B%d]", tree->inst_target_bb->block_num);
206                 break;
207         case CEE_BNE_UN:
208         case CEE_BEQ:
209         case CEE_BLT:
210         case CEE_BLT_UN:
211         case CEE_BGT:
212         case CEE_BGT_UN:
213         case CEE_BGE:
214         case CEE_BGE_UN:
215         case CEE_BLE:
216         case CEE_BLE_UN:
217                 printf ("[B%dB%d]", tree->inst_true_bb->block_num, tree->inst_false_bb->block_num);
218                 break;
219         case OP_DUMMY_USE:
220                 printf ("[%d]", (int)tree->inst_i0->inst_i0->inst_c0);
221                 break;
222         case OP_DUMMY_STORE:
223                 printf ("[%d]", (int)tree->inst_i0->inst_c0);
224                 break;
225         default:
226                 break;
227         }
228 }
229
230 static void
231 print_variable_list (MonoLocalVariableList* variables) {
232         printf ("{");
233         while (variables != NULL) {
234                 printf ("%d", variables->variable_index);
235                 if (variables->next != NULL) {
236                         printf (",");
237                 }
238                 variables = variables->next;
239         }
240         printf ("}");
241 }
242
243 static void
244 print_used_aliases(MonoInst *inst, MonoLocalVariableList* affected_variables) {
245         if (inst->ssa_op != MONO_SSA_NOP) {
246                 printf (" <");
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);
252                 } else {
253                         switch (inst->inst_i0->opcode) {
254                         case OP_LOCAL:
255                         case OP_ARG:
256                                 printf ("{%ld}", (long)inst->inst_i0->inst_c0);
257                                 break;
258                         case OP_RETARG:
259                                 printf ("{RETARG}");
260                                 break;
261                         default:
262                                 printf ("{ANY}");
263                                 break;
264                         }
265                 }
266                 printf (">");
267         }
268 }
269
270 static void
271 print_tree_with_aliasing_information (MonoAliasingInformation *info, MonoInst *tree) {
272         int arity;
273         MonoLocalVariableList* affected_variables;
274
275         if (!tree) {
276                 printf ("NULL-INST");
277                 return;
278         }
279         
280         arity = mono_burg_arity [tree->opcode];
281         
282         print_tree_node (tree);
283         
284         if (OP_IS_CALL (tree->opcode) && arity) {
285                 printf (" THIS:");
286         }
287         
288         if (arity) {
289                 printf (" (");
290                 print_tree_with_aliasing_information (info, tree->inst_i0);
291                 if (arity > 1) {
292                         printf (" ");
293                         print_tree_with_aliasing_information (info, tree->inst_i1);
294                 }
295                 printf (")");
296         }
297         
298         affected_variables = mono_aliasing_get_affected_variables_for_inst_traversing_code (info, tree);
299         print_used_aliases (tree, affected_variables);
300 }
301
302 static void
303 print_code_with_aliasing_information (MonoAliasingInformation *info) {
304         char *name = mono_method_full_name (info->cfg->method, TRUE);
305         int i;
306         
307         printf ("ALIASING DATA START (METHOD %s)\n", name);
308         printf ("ALIASED VARIABLES: ");
309         print_variable_list (info->uncontrollably_aliased_variables);
310         printf ("\n");
311         for (i = 0; i < info->cfg->num_bblocks; i++) {
312                 MonoAliasingInformationInBB *bb_info = &(info->bb [i]);
313                 MonoAliasUsageInformation *use;
314                 MonoInst *inst;
315                 
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);
320                         printf ("\n");
321                 }
322                 
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);
327                         printf ("\n");
328                 }               
329         }
330         printf ("ALIASING DATA END (METHOD %s)\n", name);
331         g_free (name);
332 }       
333
334
335 #define APPEND_USE(info,bb_info,use) do {\
336                 (use)->next = NULL;\
337                 if ((info)->next_interesting_inst != NULL) {\
338                         (info)->next_interesting_inst->next = (use);\
339                 } else {\
340                         (bb_info)->potential_alias_uses = (use);\
341                 }\
342                 (info)->next_interesting_inst = (use);\
343         } while (0)
344         
345 #define ADD_BAD_ALIAS(info,vi) do {\
346                 if (FOLLOW_ALIAS_ANALYSIS) {\
347                         printf ("ADDING BAD ALIAS FOR VARIABLE %d\n", vi);\
348                 }\
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;\
355                 }\
356         } while (0)
357
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;\
367                 }\
368                 (info)->arguments [(info)->number_of_arguments] = (inst);\
369                 (info)->arguments_aliases [(info)->number_of_arguments] = (alias);\
370                 (info)->number_of_arguments ++;\
371         } while (0)
372
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;\
377                 }\
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;\
383                 }\
384         } while (0)
385
386 static void
387 update_aliasing_information_on_inst (MonoAliasingInformation *info, MonoAliasingInformationInBB *bb_info, MonoInst *inst, MonoAliasingInformationContext *father_context) {
388         MonoAliasingInformationContext context;
389         MonoAliasValue *father_alias;
390         
391         context.inst = inst;
392         context.father = father_context;
393         if (father_context != NULL) {
394                 father_alias = &(father_context->subtree_aliases [father_context->current_subtree]);
395         } else {
396                 father_alias = NULL;
397         }
398         
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);
404                 
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);
410                 } else {
411                         context.subtree_aliases [1].type = MONO_ALIASING_TYPE_NO_ALIAS;
412                 }
413         } else {
414                 context.subtree_aliases [0].type = MONO_ALIASING_TYPE_NO_ALIAS;
415                 context.subtree_aliases [1].type = MONO_ALIASING_TYPE_NO_ALIAS;
416         }
417         
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;
428                 } else {
429                         father_alias->type = MONO_ALIASING_TYPE_ANY;
430                 }
431         } else if (inst->ssa_op == MONO_SSA_LOAD) {
432                 MonoInst *local = inst->inst_i0;
433                 
434                 if (LOAD_OF_LOCAL_GIVES_POINTER (inst,local)) {
435                         father_alias->type = MONO_ALIASING_TYPE_ANY;
436                 } else {
437                         father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
438                 }
439         } else if (OP_IS_LOAD (inst->opcode) || (inst->opcode == CEE_LDOBJ)) {
440                 MonoInst *address = inst->inst_i0;
441                 MonoLocalVariableList *affected_variables = NULL;
442                 
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];
446                         
447                         affected_variables = &(info->variables [variable_index]);
448                         if (LOAD_OF_LOCAL_GIVES_POINTER (inst,local)) {
449                                 father_alias->type = MONO_ALIASING_TYPE_ANY;
450                         } else {
451                                 father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
452                         }
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];
456                         
457                         affected_variables = &(info->variables [variable_index]);;
458                         if (LOAD_OF_LOCAL_GIVES_POINTER (inst,local)) {
459                                 father_alias->type = MONO_ALIASING_TYPE_ANY;
460                         } else {
461                                 father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
462                         }
463                 } else if (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_LOCAL_FIELD) {
464                         gssize variable_index = context.subtree_aliases [0].variable_index;
465                         
466                         affected_variables = &(info->variables [variable_index]);;
467                         if (inst->type == STACK_MP) {
468                                 father_alias->type = MONO_ALIASING_TYPE_ANY;
469                         } else {
470                                 father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
471                         }
472                 } else {
473                         if (context.subtree_aliases [0].type == MONO_ALIASING_TYPE_ANY) {
474                                 affected_variables = info->temporary_uncontrollably_aliased_variables;
475                         }
476                         if ((inst->type == STACK_MP) && (inst->inst_i0->opcode != OP_OBJADDR)) {
477                                 father_alias->type = MONO_ALIASING_TYPE_ANY;
478                         } else {
479                                 father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
480                         }
481                 }
482                 
483                 if (affected_variables != NULL) {
484                         MonoAliasUsageInformation *use = mono_mempool_alloc (info->mempool, sizeof (MonoAliasUsageInformation));
485                         
486                         inst->ssa_op = MONO_SSA_INDIRECT_LOAD;
487                         use->inst = inst;
488                         use->affected_variables = affected_variables;
489                         APPEND_USE (info,bb_info,use);
490                 }
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);
494                 }
495         } else if (OP_IS_STORE (inst->opcode) || (inst->opcode == CEE_STOBJ)) {
496                 MonoInst *address = inst->inst_i0;
497                 MonoLocalVariableList *affected_variables = NULL;
498                 
499                 if (context.subtree_aliases [1].type == MONO_ALIASING_TYPE_LOCAL) {
500                         ADD_BAD_ALIAS (info, context.subtree_aliases [1].variable_index);
501                 }
502                 
503                 if ((address->opcode == OP_LOCAL) || (address->opcode == OP_ARG)) {
504                         gssize variable_index = address->inst_c0;
505                         
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;
509                         
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;
513                 }
514                 
515                 if (affected_variables != NULL) {
516                         MonoAliasUsageInformation *use = mono_mempool_alloc (info->mempool, sizeof (MonoAliasUsageInformation));
517                         
518                         inst->ssa_op = MONO_SSA_INDIRECT_STORE;
519                         use->inst = inst;
520                         use->affected_variables = affected_variables;
521                         APPEND_USE (info,bb_info,use);
522                 }
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;
530                 int i;
531                 
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;
536                 }
537                 
538                 if (FOLLOW_ALIAS_ANALYSIS) {
539                         printf ("CALL, scanning %d arguments\n", info->number_of_arguments);
540                 }
541                 for (i = 0; i < info->number_of_arguments; i++) {
542                         //FIXME
543                         //MonoInst *argument = info->arguments [i];
544                         MonoAliasValue arguments_alias = info->arguments_aliases [i];
545                         
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);
549                                 }
550                                 ADD_UNIQUE_VARIABLE (info,alias_arguments,arguments_alias.variable_index);
551                                 //FIXME
552                                 #if 0
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);
558                                                 }
559                                         } else {
560                                                 printf ("*** ERROR: argument %d of %d: ", argument_index, sig->param_count);
561                                                 mono_print_tree_nl (argument);
562                                         }
563                                 }
564                                 #endif
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);
568                                 }
569                                 call_has_untracked_pointer_argument = TRUE;
570                         }
571                         //FIXME
572                         #if 0
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;
578                                         }
579                                 } else {
580                                         printf ("*** ERROR: argument %d of %d: ", argument_index, sig->param_count);
581                                         mono_print_tree_nl (argument);
582                                 }
583                         }
584                         #endif
585                 }
586                 
587                 if ((alias_arguments != NULL) || call_has_untracked_pointer_argument) {
588                         MonoAliasUsageInformation *use = mono_mempool_alloc (info->mempool, sizeof (MonoAliasUsageInformation));
589                         
590                         inst->ssa_op = MONO_SSA_INDIRECT_LOAD_STORE;
591                         use->inst = inst;
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;
598                         }
599                         APPEND_USE (info,bb_info,use);
600                 }
601                 
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;
605                         } else {
606                                 father_alias->type = MONO_ALIASING_TYPE_ANY;
607                         }
608                 }
609                 
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;
624                 } else {
625                         father_alias->type = MONO_ALIASING_TYPE_NO_ALIAS;
626                 }
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));
630                         
631                         inst->ssa_op = MONO_SSA_INDIRECT_STORE;
632                         use->inst = inst;
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));
637                         
638                         inst->ssa_op = MONO_SSA_INDIRECT_STORE;
639                         use->inst = inst;
640                         use->affected_variables = info->temporary_uncontrollably_aliased_variables;
641                         APPEND_USE (info,bb_info,use);
642                 }
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;
649                 }
650         } else {
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));
654                         
655                         inst->ssa_op = MONO_SSA_INDIRECT_LOAD_STORE;
656                         use->inst = inst;
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);
660                 }
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));
663                         
664                         inst->ssa_op = MONO_SSA_INDIRECT_LOAD_STORE;
665                         use->inst = inst;
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);
669                 }
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;
673                         }
674                         father_alias->type = father_type;
675                 }
676         }
677         
678         if (FOLLOW_ALIAS_ANALYSIS) {
679                 print_aliasing_context (&context);
680         }
681 }
682
683
684
685 /**
686  * mono_build_aliasing_information:
687  * @cfg: Control Flow Graph
688  *
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).
693  */
694 MonoAliasingInformation*
695 mono_build_aliasing_information (MonoCompile *cfg) {
696         MonoMemPool *pool = mono_mempool_new ();
697         MonoAliasingInformation *info = mono_mempool_alloc (pool, sizeof (MonoAliasingInformation));
698         int i;
699 #if (DEBUG_ALIAS_ANALYSIS)
700         int verbose_level = cfg->verbose_level;
701         cfg->verbose_level = 7;
702 #endif
703         
704         info->mempool = pool;
705         info->cfg = cfg;
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;
715         }
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;
723         
724         for (i = 0; i < cfg->num_bblocks; i++) {
725                 MonoBasicBlock *bb = cfg->bblocks [i];
726                 MonoAliasingInformationInBB *bb_info = &(info->bb [i]);
727                 MonoInst *inst;
728                 
729                 if (FOLLOW_ALIAS_ANALYSIS) {
730                         printf ("TRAVERSING BB %d\n", bb->block_num);
731                 }
732                 
733                 bb_info->bb = bb;
734                 bb_info->potential_alias_uses = NULL;
735                 info->next_interesting_inst = NULL;
736                 
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);
741                         }
742                         update_aliasing_information_on_inst (info, bb_info, inst, NULL);
743                 }
744                 
745                 g_assert (info->number_of_arguments == 0);
746         }
747         
748         //FIXME
749         //#if 0
750         for (i = 0; i < cfg->num_bblocks; i++) {
751                 MonoAliasingInformationInBB *bb_info = &(info->bb [i]);
752                 MonoAliasUsageInformation *use;
753                 
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;
758                                 } else {
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;
763                                                 }
764                                                 if (last->next != NULL) {
765                                                         last = last->next;
766                                                 }
767                                         }
768                                         if (last->variable_index != NO_VARIABLE_INDEX) {
769                                                 use->affected_variables = use->affected_variables->next;
770                                                 last->next = info->uncontrollably_aliased_variables;
771                                         } else {
772                                                 use->affected_variables = info->uncontrollably_aliased_variables;
773                                         }
774                                 }
775                         }
776                 }
777         }
778         //#endif
779         
780         if (DUMP_ALIAS_ANALYSIS) {
781                 print_code_with_aliasing_information (info);
782         }
783         
784 #if (DEBUG_ALIAS_ANALYSIS)
785         cfg->verbose_level = verbose_level;
786 #endif
787         
788         return info;
789 }
790
791
792 void
793 mono_destroy_aliasing_information (MonoAliasingInformation *info) {
794         mono_mempool_destroy (info->mempool);
795 }
796
797 void
798 mono_aliasing_initialize_code_traversal (MonoAliasingInformation *info, MonoBasicBlock *bb) {
799         info->next_interesting_inst = info->bb [bb->dfn].potential_alias_uses;
800 }
801
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;
810                         return result;
811                 } else if (inst->ssa_op != MONO_SSA_NOP) {
812                         if (inst->ssa_op == MONO_SSA_ADDRESS_TAKEN) {
813                                 return NULL;
814                         } else {
815                                 printf ("ERROR: instruction not found '");
816                                 //print_tree_with_aliasing_information (info, inst);
817                                 mono_print_tree (inst);
818                                 printf ("'\n");
819                                 //g_assert_not_reached ();
820                                 return NULL;
821                         }
822                 } else {
823                         return NULL;
824                 }
825         } else {
826                 return NULL;
827         }
828 }
829
830 #if 0
831 static MonoLocalVariableList*
832 mono_aliasing_get_affected_variables_for_inst_in_bb (MonoAliasingInformation *info, MonoInst *inst, MonoBasicBlock *bb) {
833         MonoAliasUsageInformation *use;
834         
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;
838                 }
839         }
840         g_assert_not_reached ();
841         return NULL;
842 }
843 #endif
844
845 MonoLocalVariableList*
846 mono_aliasing_get_affected_variables_for_inst (MonoAliasingInformation *info, MonoInst *inst) {
847         int i;
848         
849         for (i = 0; i < info->cfg->num_bblocks; i++) {
850                 MonoAliasingInformationInBB *bb_info = &(info->bb [i]);
851                 MonoAliasUsageInformation *use;
852                 
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;
856                         }
857                 }
858         }
859         g_assert_not_reached ();
860         return NULL;
861 }
862
863 #if (MONO_APPLY_DEADCE_TO_SINGLE_METHOD)
864 static char*
865 mono_deadce_method_name = NULL;
866 static gboolean check_deadce_method_name (MonoCompile *cfg) {
867         gboolean result;
868         if (mono_deadce_method_name == NULL) {
869                 mono_deadce_method_name = getenv ("MONO_DEADCE_METHOD_NAME");
870         }
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) {
874                         result = TRUE;
875                 } else {
876                         result = FALSE;
877                 }
878                 g_free (method_name);
879         } else {
880                 result = TRUE;
881         }
882         return result;
883 }
884 #endif
885
886
887
888 #if (DEBUG_DEADCE)
889 #define LOG_DEADCE (info->cfg->verbose_level > 0)
890 #else
891 #define LOG_DEADCE (info->cfg->verbose_level > 4)
892 #endif
893
894 static gboolean
895 mono_aliasing_deadce_on_inst (MonoAliasingInformation *info, MonoInst **possibly_dead_assignments, MonoInst *inst) {
896         int arity;
897         gboolean has_side_effects;
898         MonoLocalVariableList *affected_variables;
899         
900         arity = mono_burg_arity [inst->opcode];
901         
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"
905 #undef OPDEF
906 #define MINI_OP(a1,a2) case a1:
907 #include "simple-mini-ops.h"
908 #undef MINI_OP
909                 has_side_effects = FALSE;
910                 break;
911         default:
912                 has_side_effects = TRUE;
913         }
914         
915         if (arity) {
916                 if (mono_aliasing_deadce_on_inst (info, possibly_dead_assignments, inst->inst_i0)) {
917                         has_side_effects = TRUE;
918                 }
919                 if (arity > 1) {
920                         if (mono_aliasing_deadce_on_inst (info, possibly_dead_assignments, inst->inst_i1)) {
921                                 has_side_effects = TRUE;
922                         }
923                         
924                 }
925         }
926         
927         affected_variables = mono_aliasing_get_affected_variables_for_inst_traversing_code (info, inst);
928         
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) {
933                                 if (LOG_DEADCE) {
934                                         printf ("CLEARING slot %d at inst ", affected_variable->variable_index);
935                                         mono_print_tree_nl (inst);
936                                 }
937                                 possibly_dead_assignments [affected_variable->variable_index] = NULL;
938                         }
939                 }
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) {
944                                         if (LOG_DEADCE) {
945                                                 printf ("KILLING slot %d at inst ", affected_variable->variable_index);
946                                                 mono_print_tree_nl (inst);
947                                         }
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;
951                                 }
952                         }
953                         
954                         //printf ("FAST DEADCE TOTAL LOCAL\n");
955                 }
956                 
957         }
958         
959         if ((! has_side_effects) && (inst->ssa_op == MONO_SSA_STORE)) {
960                 if (LOG_DEADCE) {
961                         printf ("FILLING slot %d with inst ", (int)inst->inst_i0->inst_c0);
962                         mono_print_tree_nl (inst);
963                 }
964                 possibly_dead_assignments [inst->inst_i0->inst_c0] = inst;
965         }
966         
967         return has_side_effects;
968 }
969
970
971 void
972 mono_aliasing_deadce (MonoAliasingInformation *info) {
973         MonoCompile *cfg;
974         MonoInst **possibly_dead_assignments;
975         int i;
976                 
977         cfg = info->cfg;
978         
979         possibly_dead_assignments = alloca (cfg->num_varinfo * sizeof (MonoInst*));
980         
981         if (LOG_DEADCE) {
982                 printf ("BEFORE DEADCE START\n");
983                 mono_print_code (cfg);
984                 printf ("BEFORE DEADCE END\n");
985         }
986         
987 #if (MONO_APPLY_DEADCE_TO_SINGLE_METHOD)
988         if (! check_deadce_method_name (cfg)) {
989                 if (LOG_DEADCE) {
990                         printf ("DEADCE disabled setting MONO_DEADCE_METHOD_NAME\n");
991                 }
992                 return;
993         }
994 #endif
995         
996         for (i = 0; i < cfg->num_bblocks; i++) {
997                 MonoBasicBlock *bb;
998                 MonoInst *inst;
999                 int variable_index;
1000                 
1001                 bb = cfg->bblocks [i];
1002                 memset (possibly_dead_assignments, 0, cfg->num_varinfo * sizeof (MonoInst*));
1003                 mono_aliasing_initialize_code_traversal (info, bb);
1004                 
1005                 if (LOG_DEADCE) {
1006                         printf ("Working on BB %d\n", bb->block_num);
1007                 }
1008                 
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) {
1015                                                 if (LOG_DEADCE) {
1016                                                         printf ("FINALLY CLEARING slot %d (JMP), inst was ", variable_index);
1017                                                         mono_print_tree_nl (possibly_dead_assignments [variable_index]);
1018                                                 }
1019                                                 possibly_dead_assignments [variable_index] = NULL;
1020                                         }
1021                                 }
1022                         }
1023                 }
1024                 
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))) {
1027                                 if (LOG_DEADCE) {
1028                                         printf ("FINALLY KILLING slot %d, inst was ", variable_index);
1029                                         mono_print_tree_nl (possibly_dead_assignments [variable_index]);
1030                                 }
1031                                 
1032                                 //printf ("FAST DEADCE DEAD LOCAL\n");
1033                                 
1034                                 possibly_dead_assignments [variable_index]->opcode = OP_NOP;
1035                                 possibly_dead_assignments [variable_index]->ssa_op = MONO_SSA_NOP;
1036                         }
1037                 }
1038         }
1039         
1040         if (LOG_DEADCE) {
1041                 printf ("AFTER DEADCE START\n");
1042                 mono_print_code (cfg);
1043                 printf ("AFTER DEADCE END\n");
1044         }
1045 }