*
* (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>
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)
{