Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / mini / ssa.c
index 3e79b5e3916640cb0d6a3e9e7415b0b501ba6538..b4dc2bf65d4e55b4d5df07fb3649668f7b9cfc88 100644 (file)
@@ -1,17 +1,20 @@
-/*
- * ssa.c: Static single assign form support for the JIT compiler.
+/**
+ * \file
+ * Static single assign form support for the JIT compiler.
  *
  * Author:
  *    Dietmar Maurer (dietmar@ximian.com)
  *
  * (C) 2003 Ximian, Inc.
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #include <string.h>
 #include <mono/metadata/debug-helpers.h>
 #include <mono/metadata/mempool.h>
 #include <mono/metadata/mempool-internals.h>
+#include <mono/utils/mono-compiler.h>
 
 #ifndef DISABLE_JIT
 
@@ -157,9 +160,8 @@ typedef struct {
 
 /**
  * mono_ssa_rename_vars:
- *
- *  Implement renaming of SSA variables. Also compute def-use information in parallel.
- * @stack_history points to an area of memory which can be used for storing changes 
+ * Implement renaming of SSA variables. Also compute def-use information in parallel.
+ * \p stack_history points to an area of memory which can be used for storing changes 
  * made to the stack, so they can be reverted later.
  */
 static void
@@ -236,8 +238,13 @@ mono_ssa_rename_vars (MonoCompile *cfg, int max_vars, MonoBasicBlock *bb, gboole
                                if (var->opcode == OP_ARG)
                                        originals_used [idx] = TRUE;
 
-                               /* FIXME: */
-                               g_assert (stack_history_len < stack_history_size);
+                               if (stack_history_len + 128 > stack_history_size) {
+                                       stack_history_size += 1024;
+                                       RenameInfo *new_history = mono_mempool_alloc (cfg->mempool, sizeof (RenameInfo) * stack_history_size);
+                                       memcpy (new_history, stack_history, stack_history_len * sizeof (RenameInfo));
+                                       stack_history = new_history;
+                               }
+
                                stack_history [stack_history_len].var = stack [idx];
                                stack_history [stack_history_len].idx = idx;
                                stack_history_len ++;
@@ -477,6 +484,73 @@ mono_ssa_compute (MonoCompile *cfg)
        cfg->comp_done |= MONO_COMP_SSA;
 }
 
+/*
+ * mono_ssa_remove_gsharedvt:
+ *
+ *   Same as mono_ssa_remove, but only remove phi nodes for gsharedvt variables.
+ */
+void
+mono_ssa_remove_gsharedvt (MonoCompile *cfg)
+{
+       MonoInst *ins, *var, *move;
+       int i, j, first;
+
+       /*
+        * When compiling gsharedvt code, we need to get rid of the VPHI instructions,
+        * since they cannot be handled later in the llvm backend.
+        */
+       g_assert (cfg->comp_done & MONO_COMP_SSA);
+
+       for (i = 0; i < cfg->num_bblocks; ++i) {
+               MonoBasicBlock *bb = cfg->bblocks [i];
+
+               if (cfg->verbose_level >= 4)
+                       printf ("\nREMOVE SSA %d:\n", bb->block_num);
+
+               for (ins = bb->code; ins; ins = ins->next) {
+                       if (!(MONO_IS_PHI (ins) && ins->opcode == OP_VPHI && mini_is_gsharedvt_variable_type (&ins->klass->byval_arg)))
+                               continue;
+
+                       g_assert (ins->inst_phi_args [0] == bb->in_count);
+                       var = get_vreg_to_inst (cfg, ins->dreg);
+
+                       /* Check for PHI nodes where all the inputs are the same */
+                       first = ins->inst_phi_args [1];
+
+                       for (j = 1; j < bb->in_count; ++j)
+                               if (first != ins->inst_phi_args [j + 1])
+                                       break;
+
+                       if ((bb->in_count > 1) && (j == bb->in_count)) {
+                               ins->opcode = op_phi_to_move (ins->opcode);
+                               if (ins->opcode == OP_VMOVE)
+                                       g_assert (ins->klass);
+                               ins->sreg1 = first;
+                       } else {
+                               for (j = 0; j < bb->in_count; j++) {
+                                       MonoBasicBlock *pred = bb->in_bb [j];
+                                       int sreg = ins->inst_phi_args [j + 1];
+
+                                       if (cfg->verbose_level >= 4)
+                                               printf ("\tADD R%d <- R%d in BB%d\n", var->dreg, sreg, pred->block_num);
+                                       if (var->dreg != sreg) {
+                                               MONO_INST_NEW (cfg, move, op_phi_to_move (ins->opcode));
+                                               if (move->opcode == OP_VMOVE) {
+                                                       g_assert (ins->klass);
+                                                       move->klass = ins->klass;
+                                               }
+                                               move->dreg = var->dreg;
+                                               move->sreg1 = sreg;
+                                               mono_add_ins_to_end (pred, move);
+                                       }
+                               }
+
+                               NULLIFY_INS (ins);
+                       }
+               }
+       }
+}
+
 void
 mono_ssa_remove (MonoCompile *cfg)
 {
@@ -1447,4 +1521,8 @@ mono_ssa_loop_invariant_code_motion (MonoCompile *cfg)
        }
 }
 
-#endif /* DISABLE_JIT */
+#else /* !DISABLE_JIT */
+
+MONO_EMPTY_SOURCE_FILE (ssa);
+
+#endif /* !DISABLE_JIT */