2008-09-07 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / ssapre.c
index eafdccfa36043fc767ceda2ae9a9e5d38eddc2ef..ea817c58f03ec97eef1bacf09bf10ed2857df19b 100644 (file)
 #include <mono/metadata/debug-helpers.h>
 #include <mono/metadata/opcodes.h>
 
+#include "config.h"
+
+#ifndef DISABLE_SSA
 #include "inssel.h"
 
 #include "ssapre.h"
 
-extern guint8 mono_burg_arity [];
-
 /* Logging conditions */
 #define DUMP_LEVEL (4)
 #define TRACE_LEVEL (3)
@@ -53,7 +54,7 @@ print_argument (MonoSsapreExpressionArgument *argument) {
                        printf ("INTEGER_CONSTANT %d", argument->argument.integer_constant);
                        break;
                case MONO_SSAPRE_EXPRESSION_ARGUMENT_LONG_COSTANT:
-                       printf ("LONG_COSTANT %lld", *(argument->argument.long_constant));
+                       printf ("LONG_COSTANT %lld", (long long)*(argument->argument.long_constant));
                        break;
                case MONO_SSAPRE_EXPRESSION_ARGUMENT_FLOAT_COSTANT:
                        printf ("FLOAT_COSTANT %f", *(argument->argument.float_constant));
@@ -186,6 +187,11 @@ print_bb_info (MonoSsapreBBInfo *bb_info, gboolean print_occurrences) {
        if (bb_info->next_interesting_bb != NULL) {
                printf (", NEXT %d [ID %d]", bb_info->next_interesting_bb->cfg_dfn, bb_info->next_interesting_bb->bb->block_num);
        }
+       if (bb_info->dt_covered_by_interesting_BBs) {
+               printf (" (COVERED)");
+       } else {
+               printf (" (NEVER DOWN SAFE)");
+       }       
        printf ("\n");
        if (bb_info->has_phi) {
                printf (" PHI, class %d [ ", bb_info->phi_redundancy_class);
@@ -267,9 +273,8 @@ static void dump_code (MonoSsapreWorkArea *area) {
                MonoInst *current_inst;
                
                print_bb_info (current_bb, TRUE);
-               for (current_inst = current_bb->bb->code; current_inst != NULL; current_inst = current_inst->next) {
+               MONO_BB_FOR_EACH_INS (current_bb->bb, current_inst)
                        mono_print_tree_nl (current_inst);
-               }
        }
 }
 
@@ -336,12 +341,14 @@ analyze_argument (MonoInst *argument, MonoSsapreExpressionArgument *result) {
 static void
 analyze_expression (MonoInst *expression, MonoSsapreExpressionDescription *result) {
        switch (expression->opcode) {
+#define SSAPRE_SPECIFIC_OPS 1
 #define OPDEF(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) case a1:
-#include "ssapre-cee-ops.h"
+#include "simple-cee-ops.h"
 #undef OPDEF
 #define MINI_OP(a1,a2) case a1:
-#include "ssapre-mini-ops.h"
+#include "simple-mini-ops.h"
 #undef MINI_OP
+#undef SSAPRE_SPECIFIC_OPS
                if ( (expression->type == STACK_I4) ||
                                (expression->type == STACK_PTR) ||
                                (expression->type == STACK_MP) ||
@@ -404,7 +411,7 @@ convert_ssa_variables_to_original_names (MonoSsapreExpressionDescription *result
                result->left_argument = expression->left_argument;
        } else {
                result->left_argument.type = MONO_SSAPRE_EXPRESSION_ARGUMENT_ORIGINAL_VARIABLE;
-               original_variable = cfg->vars [expression->left_argument.argument.ssa_variable]->reg;
+               original_variable = MONO_VARINFO (cfg, expression->left_argument.argument.ssa_variable)->reg;
                if (original_variable >= 0) {
                        result->left_argument.argument.original_variable = original_variable;
                } else {
@@ -415,7 +422,7 @@ convert_ssa_variables_to_original_names (MonoSsapreExpressionDescription *result
                result->right_argument = expression->right_argument;
        } else {
                result->right_argument.type = MONO_SSAPRE_EXPRESSION_ARGUMENT_ORIGINAL_VARIABLE;
-               original_variable = cfg->vars [expression->right_argument.argument.ssa_variable]->reg;
+               original_variable = MONO_VARINFO (cfg, expression->right_argument.argument.ssa_variable)->reg;
                if (original_variable >= 0) {
                        result->right_argument.argument.original_variable = original_variable;
                } else {
@@ -457,7 +464,7 @@ is_phi_definition (MonoInst *definition) {
  * Given a variable index, checks if it is a phi definition
  * (it assumes the "area" is visible).
  */
-#define IS_PHI_DEFINITION(v) is_phi_definition (area->cfg->vars [v]->def)
+#define IS_PHI_DEFINITION(v) is_phi_definition (MONO_VARINFO (area->cfg, v)->def)
 
 /*
  * Given a variable index, checks if it is a phi definition.
@@ -466,7 +473,7 @@ is_phi_definition (MonoInst *definition) {
  */
 static int*
 get_phi_definition (MonoCompile *cfg, gssize variable) {
-       MonoInst *definition = cfg->vars [variable]->def;
+       MonoInst *definition = MONO_VARINFO (cfg, variable)->def;
        if (is_phi_definition (definition) && (definition->inst_left->inst_c0 == variable)) {
                return definition->inst_right->inst_phi_args;
        } else {
@@ -482,7 +489,7 @@ get_phi_definition (MonoCompile *cfg, gssize variable) {
  */
 static MonoSsapreBBInfo*
 get_bb_info_of_definition (MonoSsapreWorkArea *area, gssize variable) {
-       MonoBasicBlock *def_bb = area->cfg->vars [variable]->def_bb;
+       MonoBasicBlock *def_bb = MONO_VARINFO (area->cfg, variable)->def_bb;
        if (def_bb != NULL) {
                return area->bb_infos_in_cfg_dfn_order [def_bb->dfn];
        } else {
@@ -796,10 +803,10 @@ process_inst (MonoSsapreWorkArea *area, MonoInst* inst, MonoInst* previous_inst,
  * (with all the info that comes from the MonoBasicBlock).
  */
 static void
-process_bb (MonoSsapreWorkArea *area, MonoBasicBlock *bb, int *dt_dfn, int *upper_descendants) {
+process_bb (MonoSsapreWorkArea *area, MonoBasicBlock *bb, int *dt_dfn, int *upper_descendants, int current_depth) {
        MonoSsapreBBInfo *bb_info;
        int descendants;
-       GList *dominated_bb;
+       GSList *dominated_bb;
        MonoInst* current_inst;
        MonoInst* previous_inst;
        MonoSsapreFatherExpression** dummy_father_in_tree;
@@ -815,13 +822,12 @@ process_bb (MonoSsapreWorkArea *area, MonoBasicBlock *bb, int *dt_dfn, int *uppe
        bb_info->bb = bb;
        bb_info->in_bb = (MonoSsapreBBInfo**) mono_mempool_alloc (area->mempool, sizeof (MonoSsapreBBInfo*) * (bb->in_count));
        bb_info->out_bb = (MonoSsapreBBInfo**) mono_mempool_alloc (area->mempool, sizeof (MonoSsapreBBInfo*) * (bb->out_count));
-       bb_info->phi_arguments_classes = (gssize*) mono_mempool_alloc (area->mempool, sizeof (gssize) * (bb->in_count));
+       bb_info->phi_arguments_classes = (int*) mono_mempool_alloc (area->mempool, sizeof (int) * (bb->in_count));
        
        bb_info->phi_insertion_point = NULL;
        
-       current_inst = bb->code;
        previous_inst = NULL;
-       while (current_inst != NULL) {
+       MONO_BB_FOR_EACH_INS (bb, current_inst) {
                /* Ugly hack to fix missing variable definitions */
                /* (the SSA construction code should have done it already!) */
                switch (current_inst->opcode) {
@@ -836,11 +842,11 @@ process_bb (MonoSsapreWorkArea *area, MonoBasicBlock *bb, int *dt_dfn, int *uppe
                        if ((current_inst->inst_left->opcode == OP_LOCAL) || (current_inst->inst_left->opcode == OP_ARG)) {
                                int variable_index = current_inst->inst_left->inst_c0;
                                
-                               if (area->cfg->vars [variable_index]->def_bb == NULL) {
+                               if (MONO_VARINFO (area->cfg, variable_index)->def_bb == NULL) {
                                        if (area->cfg->verbose_level >= 4) {
                                                printf ("SSAPRE WARNING: variable %d has no definition, fixing.\n", variable_index);
                                        }
-                                       area->cfg->vars [variable_index]->def_bb = bb_info->bb;
+                                       MONO_VARINFO (area->cfg, variable_index)->def_bb = bb_info->bb;
                                }
                        }
                        break;
@@ -860,12 +866,14 @@ process_bb (MonoSsapreWorkArea *area, MonoBasicBlock *bb, int *dt_dfn, int *uppe
                }
                
                previous_inst = current_inst;
-               current_inst = current_inst->next;
        }
        
+       if (current_depth > area->dt_depth) {
+               area->dt_depth = current_depth;
+       }
        descendants = 0;
-       for (dominated_bb = g_list_first (bb->dominated); dominated_bb != NULL; dominated_bb = g_list_next (dominated_bb)) {
-               process_bb (area, (MonoBasicBlock*) (dominated_bb->data), dt_dfn, &descendants);
+       for (dominated_bb = bb->dominated; dominated_bb != NULL; dominated_bb = dominated_bb->next) {
+               process_bb (area, (MonoBasicBlock*) (dominated_bb->data), dt_dfn, &descendants, current_depth + 1);
        }
        bb_info->dt_descendants = descendants;
        *upper_descendants += (descendants + 1);
@@ -879,6 +887,7 @@ clean_bb_infos (MonoSsapreWorkArea *area) {
        int i;
        for (i = 0; i < area->num_bblocks; i++) {
                MonoSsapreBBInfo *bb_info = &(area->bb_infos [i]);
+               bb_info->dt_covered_by_interesting_BBs = FALSE;
                bb_info->has_phi = FALSE;
                bb_info->phi_defines_a_real_occurrence = FALSE;
                bb_info->phi_is_down_safe = FALSE;
@@ -956,6 +965,18 @@ compute_combined_iterated_dfrontier (MonoSsapreWorkArea *area, MonoBitSet *resul
        } while (change);
 }
 
+/*
+ * See paper, section 5.1, definition of "Dominate"
+ */
+static gboolean
+dominates (MonoSsapreBBInfo *dominator, MonoSsapreBBInfo *dominated) {
+       if ((dominator->dt_dfn <= dominated->dt_dfn) && (dominated->dt_dfn <= (dominator->dt_dfn + dominator->dt_descendants))) {
+               return TRUE;
+       } else {
+               return FALSE;
+       }
+}
+
 /*
  * See paper, figure 18, function Set_var_phis
  */
@@ -963,7 +984,7 @@ static void process_phi_variable_in_phi_insertion (MonoSsapreWorkArea *area, gss
        int* phi_definition = get_phi_definition (area->cfg, variable);
        
        if (phi_definition != NULL) {
-               int definition_bb = area->cfg->vars [variable]->def_bb->dfn;
+               int definition_bb = MONO_VARINFO (area->cfg, variable)->def_bb->dfn;
                if (! mono_bitset_test (phi_bbs, definition_bb)) {
                        int i;
                        mono_bitset_set (phi_bbs, definition_bb);
@@ -984,6 +1005,9 @@ phi_insertion (MonoSsapreWorkArea *area, MonoSsapreExpression *expression) {
        MonoSsapreBBInfo *current_bb = NULL;
        MonoSsapreBBInfo *previous_interesting_bb = NULL;
        int i, j, current_bb_dt_dfn;
+       int top;
+       MonoSsapreBBInfo **stack;
+       gboolean *interesting_stack;
        
        mono_bitset_clear_all (area->expression_occurrences_buffer);
        for (current_expression = expression->occurrences; current_expression != NULL; current_expression = current_expression->next) {
@@ -1023,16 +1047,60 @@ phi_insertion (MonoSsapreWorkArea *area, MonoSsapreExpression *expression) {
                }
        }
        
+       top = -1;
+       stack = (MonoSsapreBBInfo **) alloca (sizeof (MonoSsapreBBInfo *) * (area->dt_depth));
+       interesting_stack = (gboolean *) alloca (sizeof (gboolean) * (area->dt_depth));
+       
+       /* Setup the list of interesting BBs, and their "DT coverage" */
        for (current_bb = area->bb_infos, current_bb_dt_dfn = 0; current_bb_dt_dfn < area->num_bblocks; current_bb++, current_bb_dt_dfn++) {
+               gboolean current_bb_is_interesting;
+               
                if ((current_bb->first_expression_in_bb != NULL) || (current_bb->has_phi) || (current_bb->has_phi_argument)) {
+                       current_bb_is_interesting = TRUE;
+                       
                        if (previous_interesting_bb != NULL) {
                                previous_interesting_bb->next_interesting_bb = current_bb;
                        } else {
                                area->first_interesting_bb = current_bb;
                        }
                        previous_interesting_bb = current_bb;
+               } else {
+                       current_bb_is_interesting = FALSE;
+               }
+               
+               if (top >= 0) {
+                       while ((top >= 0) && (! dominates (stack [top], current_bb))) {
+                               gboolean top_covers_his_idominator = ((interesting_stack [top]) || (stack [top]->dt_covered_by_interesting_BBs));
+                               
+                               if ((top > 0) && (! top_covers_his_idominator)) {
+                                       stack [top - 1]->dt_covered_by_interesting_BBs = FALSE;
+                               }
+                               
+                               top--;
+                       }
+               } else {
+                       top = -1;
+               }
+               
+               top++;
+               
+               interesting_stack [top] = current_bb_is_interesting;
+               stack [top] = current_bb;
+               if (stack [top]->dt_descendants == 0) {
+                       stack [top]->dt_covered_by_interesting_BBs = FALSE;
+               } else {
+                       stack [top]->dt_covered_by_interesting_BBs = TRUE;
                }
        }
+       while (top > 0) {
+               gboolean top_covers_his_idominator = ((interesting_stack [top]) || (stack [top]->dt_covered_by_interesting_BBs));
+               
+               if (! top_covers_his_idominator) {
+                       stack [top - 1]->dt_covered_by_interesting_BBs = FALSE;
+               }
+               
+               top--;
+       }
 }
 
 /*
@@ -1064,18 +1132,6 @@ phi_insertion (MonoSsapreWorkArea *area, MonoSsapreExpression *expression) {
                        area->bb_on_top_of_renaming_stack->phi_argument_has_real_use = FALSE; \
                } while(0)
 
-/*
- * See paper, section 5.1, definition of "Dominate"
- */
-static gboolean
-dominates (MonoSsapreBBInfo *dominator, MonoSsapreBBInfo *dominated) {
-       if ((dominator->dt_dfn <= dominated->dt_dfn) && (dominated->dt_dfn <= (dominator->dt_dfn + dominator->dt_descendants))) {
-               return TRUE;
-       } else {
-               return FALSE;
-       }
-}
-
 /*
  * See paper, section 5.4.
  * The two passes are coded sequentially (no separate "rename1" and "rename2" functions).
@@ -1139,7 +1195,11 @@ renaming_pass (MonoSsapreWorkArea *area) {
                }
                
                if (current_bb->has_phi) {
-                       current_bb->phi_is_down_safe = TRUE;
+                       if (current_bb->dt_covered_by_interesting_BBs) {
+                               current_bb->phi_is_down_safe = TRUE;
+                       } else {
+                               current_bb->phi_is_down_safe = FALSE;
+                       }
                        current_bb->phi_redundancy_class = current_class;
                        current_class++;
                        PUSH_PHI_OCCURRENCE (current_bb);
@@ -1203,6 +1263,16 @@ renaming_pass (MonoSsapreWorkArea *area) {
                                        current_expression->redundancy_class = phi_bb->phi_redundancy_class;
                                        current_expression->defined_by_phi = phi_bb;
                                        
+                                       /* If this PHI was not "covered", it is not down safe. */
+                                       /* However, if the real occurrence is in the same BB, it */
+                                       /* actually is down safe */
+                                       if (phi_bb == current_bb) {
+                                               if (DUMP_SSAPRE) {
+                                                       printf ("PHI in bb %d [ID %d] defined occurrence %d in the same BB, so it is down safe\n", phi_bb->cfg_dfn, phi_bb->bb->block_num, current_expression->redundancy_class);
+                                               }
+                                               phi_bb->phi_is_down_safe = TRUE;
+                                       }
+                                       
                                        /*
                                         * Major difference from the paper here...
                                         * Instead of maintaining "set_for_rename2" (see figure 20), we just
@@ -1516,6 +1586,10 @@ static void finalize_availability_and_reload (MonoSsapreWorkArea *area, MonoSsap
        MonoSsapreBBInfo *current_bb = NULL;
        MonoSsapreExpressionOccurrence *current_expression = NULL;
        
+       area->occurrences_scheduled_for_reloading = 0;
+       area->arguments_scheduled_for_insertion = 0;
+       area->dominating_arguments_scheduled_for_insertion = 0;
+       
        for (current_bb = area->first_interesting_bb; current_bb != NULL; current_bb = current_bb->next_interesting_bb) {
                if (current_bb->has_phi) {
                        if (current_bb->phi_can_be_available && ! current_bb->phi_is_later) {
@@ -1539,6 +1613,9 @@ static void finalize_availability_and_reload (MonoSsapreWorkArea *area, MonoSsap
                                availability_table [current_expression->redundancy_class].class_defined_by_real_occurrence = current_expression;
                        } else {
                                current_expression->reload = TRUE;
+                               
+                               area->occurrences_scheduled_for_reloading ++;
+                               
                                current_expression->defined_by_phi = availability_table [current_expression->redundancy_class].class_defined_by_phi;
                                current_expression->defined_by_real_occurrence = availability_table [current_expression->redundancy_class].class_defined_by_real_occurrence;
                        }
@@ -1554,6 +1631,12 @@ static void finalize_availability_and_reload (MonoSsapreWorkArea *area, MonoSsap
                                                (! ((current_bb->phi_argument_defined_by_phi->phi_can_be_available) && (! current_bb->phi_argument_defined_by_phi->phi_is_later)))
                                        ))) {
                                current_bb->phi_argument_needs_insert = TRUE;
+                               
+                               area->arguments_scheduled_for_insertion ++;
+                               if (dominates (current_bb, phi_bb)) {
+                                       area->dominating_arguments_scheduled_for_insertion ++;
+                               }
+                               
                                current_bb->phi_argument_defined_by_real_occurrence = NULL;
                                current_bb->phi_argument_defined_by_phi = NULL;
                        } else {
@@ -1611,10 +1694,16 @@ static void finalize_save (MonoSsapreWorkArea *area) {
        }
 }
 
+#define OP_IS_CHEAP(op) (((op)==CEE_ADD)||((op)==CEE_SUB))
+#define EXPRESSION_HAS_ICONST(d) (((d).left_argument.type==MONO_SSAPRE_EXPRESSION_ARGUMENT_INTEGER_CONSTANT)||((d).right_argument.type==MONO_SSAPRE_EXPRESSION_ARGUMENT_INTEGER_CONSTANT))
+#define EXPRESSION_IS_CHEAP(d) ((OP_IS_CHEAP ((d).opcode))&&(EXPRESSION_HAS_ICONST ((d))))
+#define REDUNDANCY_IS_SMALL(a) (((a)->occurrences_scheduled_for_reloading < 2)&&((a)->dominating_arguments_scheduled_for_insertion < 1))
+
 /*
- * Perform all "finalize" steps
+ * Perform all "finalize" steps.
+ * Return TRUE if we must go on with code_motion.
  */
-static void finalize (MonoSsapreWorkArea *area) {
+static gboolean finalize (MonoSsapreWorkArea *area) {
        MonoSsapreAvailabilityTableElement *availability_table = alloca (sizeof (MonoSsapreAvailabilityTableElement) * (area->number_of_classes));
        int i;
        
@@ -1624,7 +1713,14 @@ static void finalize (MonoSsapreWorkArea *area) {
        }
        
        finalize_availability_and_reload (area, availability_table);
-       finalize_save (area);
+       
+       /* Tuning: if the redundancy is not worth handling, give up */
+       if ((EXPRESSION_IS_CHEAP (area->current_expression->description)) && (REDUNDANCY_IS_SMALL (area))) {
+               return FALSE;
+       } else {
+               finalize_save (area);
+               return TRUE;
+       }
 }
 
 /*
@@ -1747,8 +1843,8 @@ static void code_motion (MonoSsapreWorkArea *area) {
                        if (original_variable_index == BOTTOM_REDUNDANCY_CLASS) {
                                original_variable_index = new_var->inst_c0;
                        }
-                       area->cfg->vars [new_var->inst_c0]->reg = original_variable_index;
-                       area->cfg->vars [new_var->inst_c0]->def_bb = current_bb->bb;
+                       MONO_VARINFO (area->cfg, new_var->inst_c0)->reg = original_variable_index;
+                       MONO_VARINFO (area->cfg, new_var->inst_c0)->def_bb = current_bb->bb;
                } else {
                        current_bb->phi_variable_index = BOTTOM_REDUNDANCY_CLASS;
                }
@@ -1763,8 +1859,8 @@ static void code_motion (MonoSsapreWorkArea *area) {
                                if (original_variable_index == BOTTOM_REDUNDANCY_CLASS) {
                                        original_variable_index = new_var->inst_c0;
                                }
-                               area->cfg->vars [new_var->inst_c0]->reg = original_variable_index;
-                               area->cfg->vars [new_var->inst_c0]->def_bb = current_bb->bb;
+                               MONO_VARINFO (area->cfg, new_var->inst_c0)->reg = original_variable_index;
+                               MONO_VARINFO (area->cfg, new_var->inst_c0)->def_bb = current_bb->bb;
                        } else {
                                current_expression->variable_index = BOTTOM_REDUNDANCY_CLASS;
                        }
@@ -1776,8 +1872,8 @@ static void code_motion (MonoSsapreWorkArea *area) {
                        if (original_variable_index == BOTTOM_REDUNDANCY_CLASS) {
                                original_variable_index = new_var->inst_c0;
                        }
-                       area->cfg->vars [new_var->inst_c0]->reg = original_variable_index;
-                       area->cfg->vars [new_var->inst_c0]->def_bb = current_bb->bb;
+                       MONO_VARINFO (area->cfg, new_var->inst_c0)->reg = original_variable_index;
+                       MONO_VARINFO (area->cfg, new_var->inst_c0)->def_bb = current_bb->bb;
                } else {
                        current_bb->phi_argument_variable_index = BOTTOM_REDUNDANCY_CLASS;
                }
@@ -1790,7 +1886,7 @@ static void code_motion (MonoSsapreWorkArea *area) {
                        int in_bb;
                        
                        NEW_INST (phi, OP_PHI);
-                       phi->inst_c0 = area->cfg->vars [current_bb->phi_variable_index]->reg;
+                       phi->inst_c0 = MONO_VARINFO (area->cfg, current_bb->phi_variable_index)->reg;
                        phi->inst_phi_args = mono_mempool_alloc (area->cfg->mempool, (sizeof (int) * ((current_bb->in_count) + 1)));
                        phi->inst_phi_args [0] = current_bb->in_count;
                        for (in_bb = 0; in_bb < current_bb->in_count; in_bb++) {
@@ -1815,7 +1911,7 @@ static void code_motion (MonoSsapreWorkArea *area) {
                                store->next = current_bb->bb->code;
                                current_bb->bb->code = store;
                        }
-                       area->cfg->vars [current_bb->phi_variable_index]->def = store;
+                       MONO_VARINFO (area->cfg, current_bb->phi_variable_index)->def = store;
                        current_bb->phi_insertion_point = store;
                        
                        area->added_phis ++;
@@ -1835,7 +1931,7 @@ static void code_motion (MonoSsapreWorkArea *area) {
                                        store->next = current_bb->bb->code;
                                        current_bb->bb->code = store;
                                }
-                               area->cfg->vars [current_expression->variable_index]->def = store;
+                               MONO_VARINFO (area->cfg, current_expression->variable_index)->def = store;
                                mono_compile_make_var_load (area->cfg, current_expression->occurrence, current_expression->variable_index);
                                if (current_expression->father_in_tree != NULL) {
                                        handle_father_expression (area, current_expression, store);
@@ -1884,7 +1980,7 @@ static void code_motion (MonoSsapreWorkArea *area) {
                        
                        inserted_expression = create_expression (area, &expression_description, &prototype_occurrence);
                        store = mono_compile_create_var_store (area->cfg, current_bb->phi_argument_variable_index, inserted_expression);
-                       area->cfg->vars [current_bb->phi_argument_variable_index]->def = store;
+                       MONO_VARINFO (area->cfg, current_bb->phi_argument_variable_index)->def = store;
                        store->next = NULL;
                        mono_add_ins_to_end (current_bb->bb, store);
                        
@@ -1921,8 +2017,14 @@ process_expression (MonoSsapreWorkArea *area) {
        down_safety (area);
        compute_can_be_available (area);
        compute_later (area);
-       finalize (area);
-       code_motion (area);
+       if (finalize (area)) {
+               code_motion (area);
+       } else {
+               if (area->cfg->verbose_level >= TRACE_LEVEL) {
+                       printf ("SSAPRE CODE MOTION SKIPPED\n");
+               }
+       }
+       
        
        if (area->cfg->verbose_level >= DUMP_LEVEL) {
                printf ("START DUMP OF BB INFOS\n");
@@ -2000,13 +2102,17 @@ mono_perform_ssapre (MonoCompile *cfg) {
        if (area.cfg->verbose_level >= LOG_LEVEL) {
                printf ("SSAPRE STARTS PROCESSING METHOD %s\n", mono_method_full_name (cfg->method, TRUE));
        }
+       if (area.cfg->verbose_level >= DUMP_LEVEL) {
+               mono_print_code (area.cfg, "BEFORE SSAPRE");
+       }
        
        area.first_in_queue = NULL;
        area.last_in_queue = NULL;
        area.current_occurrence = (MonoSsapreExpressionOccurrence*) mono_mempool_alloc (area.mempool, sizeof (MonoSsapreExpressionOccurrence));
        dt_dfn = 0;
        descendants = 0;
-       process_bb (&area, cfg->bblocks [0], &dt_dfn, &descendants);
+       area.dt_depth = 0;
+       process_bb (&area, cfg->bblocks [0], &dt_dfn, &descendants, 1);
        for (block = 0; block < area.num_bblocks; block++) {
                MonoSsapreBBInfo *bb_info = &(area.bb_infos [block]);
                MonoBasicBlock *bb = bb_info->bb;
@@ -2036,9 +2142,15 @@ mono_perform_ssapre (MonoCompile *cfg) {
                process_expression (&area);             
        }
        
+       if (area.cfg->verbose_level >= DUMP_LEVEL) {
+               mono_print_code (area.cfg, "AFTER SSAPRE");
+       }
        if (area.cfg->verbose_level >= TRACE_LEVEL) {
                printf ("SSAPRE ENDS PROCESSING METHOD %s\n", mono_method_full_name (cfg->method, TRUE));
        }
        
        mono_mempool_destroy (area.mempool);
 }
+
+#endif /* DISABLE_SSA */
+