Build mono runtime under none desktop Windows API family, adjustments and cleanup.
[mono.git] / mono / mini / ssa.c
index 3e79b5e3916640cb0d6a3e9e7415b0b501ba6538..d70788c6afb39ce430fcde647838b3ca7689e66b 100644 (file)
@@ -6,12 +6,14 @@
  *
  * (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
 
@@ -477,6 +479,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 +1516,8 @@ mono_ssa_loop_invariant_code_motion (MonoCompile *cfg)
        }
 }
 
-#endif /* DISABLE_JIT */
+#else /* !DISABLE_JIT */
+
+MONO_EMPTY_SOURCE_FILE (ssa);
+
+#endif /* !DISABLE_JIT */