Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / mini / ssa.c
index 8f804b85c93ee73019f43f97f19fb3b6e6aca8a4..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
 
@@ -141,7 +144,7 @@ static inline void
 record_use (MonoCompile *cfg, MonoInst *var, MonoBasicBlock *bb, MonoInst *ins)
 {
        MonoMethodVar *info;
-       MonoVarUsageInfo *ui = mono_mempool_alloc (cfg->mempool, sizeof (MonoVarUsageInfo));
+       MonoVarUsageInfo *ui = (MonoVarUsageInfo *)mono_mempool_alloc (cfg->mempool, sizeof (MonoVarUsageInfo));
 
        info = MONO_VARINFO (cfg, var->inst_c0);
        
@@ -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 ++;
@@ -352,7 +359,7 @@ mono_ssa_compute (MonoCompile *cfg)
        mono_compile_dominator_info (cfg, MONO_COMP_DOM | MONO_COMP_IDOM | MONO_COMP_DFRONTIER);
 
        bitsize = mono_bitset_alloc_size (cfg->num_bblocks, 0);
-       buf = buf_start = g_malloc0 (mono_bitset_alloc_size (cfg->num_bblocks, 0) * cfg->num_varinfo);
+       buf = buf_start = (guint8 *)g_malloc0 (mono_bitset_alloc_size (cfg->num_bblocks, 0) * cfg->num_varinfo);
 
        for (i = 0; i < cfg->num_varinfo; ++i) {
                vinfo [i].def_in = mono_bitset_mem_new (buf, cfg->num_bblocks, 0);
@@ -434,7 +441,7 @@ mono_ssa_compute (MonoCompile *cfg)
                        else
                                ins->klass = var->klass;
 
-                       ins->inst_phi_args =  mono_mempool_alloc0 (cfg->mempool, sizeof (int) * (cfg->bblocks [idx]->in_count + 1));
+                       ins->inst_phi_args = (int *)mono_mempool_alloc0 (cfg->mempool, sizeof (int) * (cfg->bblocks [idx]->in_count + 1));
                        ins->inst_phi_args [0] = cfg->bblocks [idx]->in_count;
 
                        /* For debugging */
@@ -457,7 +464,7 @@ mono_ssa_compute (MonoCompile *cfg)
 
        /* Renaming phase */
 
-       stack = alloca (sizeof (MonoInst *) * cfg->num_varinfo);
+       stack = (MonoInst **)alloca (sizeof (MonoInst *) * cfg->num_varinfo);
        memset (stack, 0, sizeof (MonoInst *) * cfg->num_varinfo);
 
        lvreg_stack = g_new0 (guint32, cfg->next_vreg);
@@ -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)
 {
@@ -937,7 +1011,7 @@ visit_inst (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, GList **cvars,
 
                if (MONO_IS_JUMP_TABLE (ins)) {
                        int i;
-                       MonoJumpInfoBBTable *table = MONO_JUMP_TABLE_FROM_INS (ins);
+                       MonoJumpInfoBBTable *table = (MonoJumpInfoBBTable *)MONO_JUMP_TABLE_FROM_INS (ins);
 
                        if (!ins->next || ins->next->opcode != OP_PADD) {
                                /* The PADD was optimized away */
@@ -973,7 +1047,7 @@ visit_inst (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, GList **cvars,
 
                if (ins->opcode == OP_SWITCH) {
                        int i;
-                       MonoJumpInfoBBTable *table = ins->inst_p0;
+                       MonoJumpInfoBBTable *table = (MonoJumpInfoBBTable *)ins->inst_p0;
 
                        for (i = 0; i < table->table_size; i++)
                                if (table->table [i])
@@ -1049,7 +1123,7 @@ fold_ins (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, MonoInst **carray
 
                if (MONO_IS_JUMP_TABLE (ins)) {
                        int i;
-                       MonoJumpInfoBBTable *table = MONO_JUMP_TABLE_FROM_INS (ins);
+                       MonoJumpInfoBBTable *table = (MonoJumpInfoBBTable *)MONO_JUMP_TABLE_FROM_INS (ins);
 
                        if (!ins->next || ins->next->opcode != OP_PADD) {
                                /* The PADD was optimized away */
@@ -1363,22 +1437,10 @@ mono_ssa_loop_invariant_code_motion (MonoCompile *cfg)
                if (bb != h)
                        continue;
                MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
-                       gboolean is_class_init = FALSE;
-
                        /*
                         * Try to move instructions out of loop headers into the preceeding bblock.
                         */
-                       if (ins->opcode == OP_VOIDCALL) {
-                               MonoCallInst *call = (MonoCallInst*)ins;
-
-                               if (call->fptr_is_patch) {
-                                       MonoJumpInfo *ji = (MonoJumpInfo*)call->fptr;
-
-                                       if (ji->type == MONO_PATCH_INFO_CLASS_INIT)
-                                               is_class_init = TRUE;
-                               }
-                       }
-                       if (ins->opcode == OP_LDLEN || ins->opcode == OP_STRLEN || ins->opcode == OP_CHECK_THIS || ins->opcode == OP_AOTCONST || is_class_init) {
+                       if (ins->opcode == OP_LDLEN || ins->opcode == OP_STRLEN || ins->opcode == OP_CHECK_THIS || ins->opcode == OP_AOTCONST || ins->opcode == OP_GENERIC_CLASS_INIT) {
                                gboolean skip;
                                int sreg;
 
@@ -1459,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 */