Author: zoltan
Date: 2006-03-21 10:22:37 -0500 (Tue, 21 Mar 2006)
New Revision: 58222
Modified:
branches/vargaz/mini-linear-il/mono/mono/mini/method-to-ir.c
branches/vargaz/mini-linear-il/mono/mono/mini/mini-amd64.c
Log:
More vtype fixes/optimizations && amd64 fixes.
Modified: branches/vargaz/mini-linear-il/mono/mono/mini/method-to-ir.c
===================================================================
--- branches/vargaz/mini-linear-il/mono/mono/mini/method-to-ir.c
2006-03-21 15:02:15 UTC (rev 58221)
+++ branches/vargaz/mini-linear-il/mono/mono/mini/method-to-ir.c
2006-03-21 15:22:37 UTC (rev 58222)
@@ -1713,6 +1713,12 @@
case MONO_TYPE_VALUETYPE:
case MONO_TYPE_TYPEDBYREF:
return STACK_VTYPE;
+ case MONO_TYPE_GENERICINST:
+ if (mono_type_generic_inst_is_valuetype (t))
+ return STACK_VTYPE;
+ else
+ return STACK_OBJ;
+ break;
default:
g_assert_not_reached ();
}
@@ -2923,7 +2929,7 @@
static MonoInst*
handle_box (MonoCompile *cfg, MonoInst *val, const guchar *ip, MonoClass
*klass)
{
- MonoInst *alloc;
+ MonoInst *alloc, *ins;
if (mono_class_is_nullable (klass)) {
MonoMethod* method = mono_class_get_method_from_name (klass,
"Box", 1);
@@ -2932,7 +2938,9 @@
alloc = handle_alloc (cfg, klass, TRUE, ip);
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, mono_type_to_store_membase
(&klass->byval_arg), alloc->dreg, sizeof (MonoObject), val->dreg);
+ EMIT_NEW_STORE_MEMBASE (cfg, ins, mono_type_to_store_membase
(&klass->byval_arg), alloc->dreg, sizeof (MonoObject), val->dreg);
+ if (ins->opcode == OP_STOREV_MEMBASE)
+ ins->klass = klass;
return alloc;
}
@@ -6138,10 +6146,8 @@
}
- if (cmethod && cmethod->klass->generic_container) {
- // G_BREAKPOINT ();
+ if (cmethod && cmethod->klass->generic_container)
UNVERIFIED;
- }
CHECK_STACK (n);
@@ -6177,7 +6183,6 @@
}
if (*ip != CEE_CALLI && check_call_signature (cfg,
fsig, sp)) {
- // G_BREAKPOINT ();
UNVERIFIED;
}
@@ -7243,6 +7248,10 @@
stack_type = type_to_stack_type
(&klass->byval_arg);
dreg = alloc_dreg (cfg, stack_type);
EMIT_NEW_LOAD_MEMBASE (cfg, dest,
mono_type_to_load_membase (&klass->byval_arg), dreg, sp[0]->dreg, 0);
+ if (dest->opcode == OP_LOADV_MEMBASE) {
+ dest->type = STACK_VTYPE;
+ dest->klass = klass;
+ }
*sp++ = dest;
}
@@ -7391,6 +7400,9 @@
MonoInst *store;
EMIT_NEW_STORE_MEMBASE (cfg, store,
mono_type_to_store_membase (field->type), sp [0]->dreg, foffset, sp [1]->dreg);
+ if (store->opcode == OP_STOREV_MEMBASE)
+ store->klass =
mono_class_from_mono_type (field->type);
+
store->flags |= ins_flag;
ins_flag = 0;
}
@@ -9292,6 +9304,8 @@
case 'f':
mono_compile_create_var_for_vreg (cfg, &mono_defaults.double_class->byval_arg,
OP_LOCAL, vreg);
break;
+ case 'v':
+ break;
default:
g_assert_not_reached ();
}
@@ -9714,7 +9728,7 @@
* - the vtype optimizations are blocked by the LDADDR opcodes generated for
* accessing vtype fields and passing/receiving them in calls.
* - in the managed->native wrappers, place a pop before the call to
interrupt_checkpoint
- * - port the lea optimization to amd64
+ * - bench.exe hangs on x86 when ssa is enabled
* - LAST MERGE: 57988.
*/
Modified: branches/vargaz/mini-linear-il/mono/mono/mini/mini-amd64.c
===================================================================
--- branches/vargaz/mini-linear-il/mono/mono/mini/mini-amd64.c 2006-03-21
15:02:15 UTC (rev 58221)
+++ branches/vargaz/mini-linear-il/mono/mono/mini/mini-amd64.c 2006-03-21
15:22:37 UTC (rev 58222)
@@ -1433,6 +1433,19 @@
return call;
}
+/* FIXME: Remove these later */
+#define NEW_VARLOADA(cfg,dest,var,vartype) do { \
+ MONO_INST_NEW ((cfg), (dest), OP_LDADDR); \
+ (dest)->ssa_op = MONO_SSA_ADDRESS_TAKEN; \
+ (dest)->inst_p0 = (var); \
+ (var)->flags |= MONO_INST_INDIRECT; \
+ (dest)->type = STACK_MP; \
+ (dest)->klass = (var)->klass; \
+ (dest)->dreg = mono_alloc_dreg ((cfg), STACK_MP); \
+ } while (0)
+
+#define EMIT_NEW_VARLOADA(cfg,dest,var,vartype) do { NEW_VARLOADA ((cfg),
(dest), (var), (vartype)); MONO_ADD_INS ((cfg)->cbb, (dest)); } while (0)
+
MonoCallInst*
mono_arch_call_opcode2 (MonoCompile *cfg, MonoCallInst *call, int is_virtual) {
MonoInst *arg, *in;
@@ -1460,6 +1473,8 @@
arg->sreg1 = in->dreg;
if ((i >= sig->hasthis) && (MONO_TYPE_ISSTRUCT(sig->params [i -
sig->hasthis]))) {
+ MonoInst *src_var = get_vreg_to_inst (cfg, in->dreg);
+ MonoInst *src;
guint32 align;
guint32 size;
@@ -1479,16 +1494,25 @@
*/
size = mono_class_value_size
(in->klass, &align);
}
+
+ g_assert (in->klass);
+
+ // FIXME:
+ if (!src_var)
+ src_var = mono_compile_create_var_for_vreg
(cfg, &in->klass->byval_arg, OP_LOCAL, in->dreg);
+
if (ainfo->storage == ArgValuetypeInReg) {
MonoInst *load, *arg;
int part;
+ EMIT_NEW_VARLOADA ((cfg), (src), src_var,
src_var->inst_vtype);
+
for (part = 0; part < 2; ++part) {
if (ainfo->pair_storage [part] ==
ArgNone)
continue;
MONO_INST_NEW (cfg, load,
arg_storage_to_load_membase (ainfo->pair_storage [part]));
- load->inst_basereg = in->dreg;
+ load->inst_basereg = src->dreg;
load->inst_offset = part * sizeof
(gpointer);
switch (ainfo->pair_storage [part]) {
@@ -1509,19 +1533,22 @@
}
}
else {
+ if (size > 0)
+ EMIT_NEW_VARLOADA ((cfg), (src),
src_var, src_var->inst_vtype);
+
if (size == 0) {
} else if (size == 8) {
/* Can't use this for < 8 since it does
an 8 byte memory load */
arg->opcode = OP_X86_PUSH_MEMBASE;
- arg->inst_basereg = in->dreg;
+ arg->inst_basereg = src->dreg;
arg->inst_offset = 0;
MONO_ADD_INS (cfg->cbb, arg);
} else if (size <= 40) {
MONO_EMIT_NEW_BIALU_IMM (cfg,
OP_SUB_IMM, X86_ESP, X86_ESP, ALIGN_TO (size, 8));
- mini_emit_memcpy2 (cfg, X86_ESP, 0,
in->dreg, 0, size, 0);
+ mini_emit_memcpy2 (cfg, X86_ESP, 0,
src->dreg, 0, size, 0);
} else {
arg->opcode = OP_X86_PUSH_OBJ;
- arg->inst_basereg = in->dreg;
+ arg->inst_basereg = src->dreg;
arg->inst_offset = 0;
arg->inst_imm = size;
MONO_ADD_INS (cfg->cbb, arg);
@@ -1791,8 +1818,222 @@
#define INST_IGNORES_CFLAGS(opcode) (!(((opcode) == OP_ADC) || ((opcode) ==
OP_ADC_IMM) || ((opcode) == OP_IADC) || ((opcode) == OP_IADC_IMM) || ((opcode)
== OP_SBB) || ((opcode) == OP_SBB_IMM) || ((opcode) == OP_ISBB) || ((opcode) ==
OP_ISBB_IMM)))
-//#define INST_IGNORES_CFLAGS(ins) (((ins)->opcode == CEE_BR) ||
((ins)->opcode == OP_BR) || ((ins)->opcode == OP_STORE_MEMBASE_IMM) ||
((ins)->opcode == OP_STOREI8_MEMBASE_REG) || ((ins)->opcode == OP_MOVE) ||
((ins)->opcode == OP_ICONST) || ((ins)->opcode == OP_I8CONST) || ((ins)->opcode
== OP_LOAD_MEMBASE))
+/*
+ * peephole_pass_1:
+ *
+ * Perform peephole opts which should/can be performed before local regalloc
+ */
+static void
+peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
+{
+ MonoInst *ins, *last_ins = NULL;
+ ins = bb->code;
+ while (ins) {
+
+ switch (ins->opcode) {
+ case OP_ADD_IMM:
+ case OP_IADD_IMM:
+ if ((ins->sreg1 < MONO_MAX_IREGS) && (ins->dreg >=
MONO_MAX_IREGS)) {
+ /*
+ * X86_LEA is like ADD, but doesn't have the
+ * sreg1==dreg restriction.
+ */
+ ins->opcode = OP_X86_LEA_MEMBASE;
+ ins->inst_basereg = ins->sreg1;
+ }
+ break;
+ case OP_COMPARE_IMM:
+ case OP_LCOMPARE_IMM:
+ /* OP_COMPARE_IMM (reg, 0)
+ * -->
+ * OP_AMD64_TEST_NULL (reg)
+ */
+ if (!ins->inst_imm)
+ ins->opcode = OP_AMD64_TEST_NULL;
+ break;
+ case OP_ICOMPARE_IMM:
+ if (!ins->inst_imm)
+ ins->opcode = OP_X86_TEST_NULL;
+ break;
+ case OP_AMD64_ICOMPARE_MEMBASE_IMM:
+ /*
+ * OP_STORE_MEMBASE_REG reg, offset(basereg)
+ * OP_X86_COMPARE_MEMBASE_IMM offset(basereg), imm
+ * -->
+ * OP_STORE_MEMBASE_REG reg, offset(basereg)
+ * OP_COMPARE_IMM reg, imm
+ *
+ * Note: if imm = 0 then OP_COMPARE_IMM replaced with
OP_X86_TEST_NULL
+ */
+ if (last_ins && (last_ins->opcode ==
OP_STOREI4_MEMBASE_REG) &&
+ ins->inst_basereg == last_ins->inst_destbasereg &&
+ ins->inst_offset == last_ins->inst_offset) {
+ ins->opcode = OP_ICOMPARE_IMM;
+ ins->sreg1 = last_ins->sreg1;
+
+ /* check if we can remove cmp reg,0
with test null */
+ if (!ins->inst_imm)
+ ins->opcode = OP_X86_TEST_NULL;
+ }
+
+ break;
+ case OP_LOAD_MEMBASE:
+ case OP_LOADI4_MEMBASE:
+ /*
+ * Note: if reg1 = reg2 the load op is removed
+ *
+ * OP_STORE_MEMBASE_REG reg1, offset(basereg)
+ * OP_LOAD_MEMBASE offset(basereg), reg2
+ * -->
+ * OP_STORE_MEMBASE_REG reg1, offset(basereg)
+ * OP_MOVE reg1, reg2
+ */
+ if (last_ins && (last_ins->opcode ==
OP_STOREI4_MEMBASE_REG
+ || last_ins->opcode ==
OP_STORE_MEMBASE_REG) &&
+ ins->inst_basereg == last_ins->inst_destbasereg &&
+ ins->inst_offset == last_ins->inst_offset) {
+ if (ins->dreg == last_ins->sreg1) {
+ last_ins->next = ins->next;
+ ins = ins->next;
+ continue;
+ } else {
+ //static int c = 0; printf ("MATCHX %s
%d\n", cfg->method->name,c++);
+ ins->opcode = OP_MOVE;
+ ins->sreg1 = last_ins->sreg1;
+ }
+
+ /*
+ * Note: reg1 must be different from the basereg in the
second load
+ * Note: if reg1 = reg2 is equal then second load is
removed
+ *
+ * OP_LOAD_MEMBASE offset(basereg), reg1
+ * OP_LOAD_MEMBASE offset(basereg), reg2
+ * -->
+ * OP_LOAD_MEMBASE offset(basereg), reg1
+ * OP_MOVE reg1, reg2
+ */
+ } if (last_ins && (last_ins->opcode == OP_LOADI4_MEMBASE
+ || last_ins->opcode ==
OP_LOAD_MEMBASE) &&
+ ins->inst_basereg != last_ins->dreg &&
+ ins->inst_basereg == last_ins->inst_basereg &&
+ ins->inst_offset == last_ins->inst_offset) {
+
+ if (ins->dreg == last_ins->dreg) {
+ last_ins->next = ins->next;
+ ins = ins->next;
+ continue;
+ } else {
+ ins->opcode = OP_MOVE;
+ ins->sreg1 = last_ins->dreg;
+ }
+
+ //g_assert_not_reached ();
+
+#if 0
+ /*
+ * OP_STORE_MEMBASE_IMM imm, offset(basereg)
+ * OP_LOAD_MEMBASE offset(basereg), reg
+ * -->
+ * OP_STORE_MEMBASE_IMM imm, offset(basereg)
+ * OP_ICONST reg, imm
+ */
+ } else if (last_ins && (last_ins->opcode ==
OP_STOREI4_MEMBASE_IMM
+ || last_ins->opcode ==
OP_STORE_MEMBASE_IMM) &&
+ ins->inst_basereg ==
last_ins->inst_destbasereg &&
+ ins->inst_offset == last_ins->inst_offset) {
+ //static int c = 0; printf ("MATCHX %s %d\n",
cfg->method->name,c++);
+ ins->opcode = OP_ICONST;
+ ins->inst_c0 = last_ins->inst_imm;
+ g_assert_not_reached (); // check this rule
+#endif
+ }
+ break;
+ case OP_LOADU1_MEMBASE:
+ case OP_LOADI1_MEMBASE:
+ /*
+ * Note: if reg1 = reg2 the load op is removed
+ *
+ * OP_STORE_MEMBASE_REG reg1, offset(basereg)
+ * OP_LOAD_MEMBASE offset(basereg), reg2
+ * -->
+ * OP_STORE_MEMBASE_REG reg1, offset(basereg)
+ * OP_MOVE reg1, reg2
+ */
+ if (last_ins && (last_ins->opcode ==
OP_STOREI1_MEMBASE_REG) &&
+ ins->inst_basereg ==
last_ins->inst_destbasereg &&
+ ins->inst_offset ==
last_ins->inst_offset) {
+ if (ins->dreg == last_ins->sreg1) {
+ last_ins->next = ins->next;
+ ins = ins->next;
+ continue;
+ } else {
+ //static int c = 0; printf ("MATCHX %s
%d\n", cfg->method->name,c++);
+ ins->opcode = OP_MOVE;
+ ins->sreg1 = last_ins->sreg1;
+ }
+ }
+ break;
+ case OP_LOADU2_MEMBASE:
+ case OP_LOADI2_MEMBASE:
+ /*
+ * Note: if reg1 = reg2 the load op is removed
+ *
+ * OP_STORE_MEMBASE_REG reg1, offset(basereg)
+ * OP_LOAD_MEMBASE offset(basereg), reg2
+ * -->
+ * OP_STORE_MEMBASE_REG reg1, offset(basereg)
+ * OP_MOVE reg1, reg2
+ */
+ if (last_ins && (last_ins->opcode ==
OP_STOREI2_MEMBASE_REG) &&
+ ins->inst_basereg ==
last_ins->inst_destbasereg &&
+ ins->inst_offset ==
last_ins->inst_offset) {
+ if (ins->dreg == last_ins->sreg1) {
+ last_ins->next = ins->next;
+ ins = ins->next;
+ continue;
+ } else {
+ //static int c = 0; printf ("MATCHX %s
%d\n", cfg->method->name,c++);
+ ins->opcode = OP_MOVE;
+ ins->sreg1 = last_ins->sreg1;
+ }
+ }
+ break;
+ case CEE_CONV_I4:
+ case CEE_CONV_U4:
+ case OP_MOVE:
+ /*
+ * Removes:
+ *
+ * OP_MOVE reg, reg
+ */
+ if (ins->dreg == ins->sreg1) {
+ if (last_ins)
+ last_ins->next = ins->next;
+ ins = ins->next;
+ continue;
+ }
+ /*
+ * Removes:
+ *
+ * OP_MOVE sreg, dreg
+ * OP_MOVE dreg, sreg
+ */
+ if (last_ins && last_ins->opcode == OP_MOVE &&
+ ins->sreg1 == last_ins->dreg &&
+ ins->dreg == last_ins->sreg1) {
+ last_ins->next = ins->next;
+ ins = ins->next;
+ continue;
+ }
+ break;
+ }
+ last_ins = ins;
+ ins = ins->next;
+ }
+ bb->last_ins = last_ins;
+}
+
static void
peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb)
{
@@ -1820,42 +2061,21 @@
* in the initlocals bblock.
*/
for (ins2 = ins->next; ins2; ins2 = ins2->next)
{
- if (((ins2->opcode ==
OP_STORE_MEMBASE_IMM) || (ins2->opcode == OP_STOREI4_MEMBASE_IMM) ||
(ins2->opcode == OP_STOREI8_MEMBASE_IMM)) && (ins2->inst_imm == 0)) {
+ if (((ins2->opcode ==
OP_STORE_MEMBASE_IMM) || (ins2->opcode == OP_STOREI4_MEMBASE_IMM) ||
(ins2->opcode == OP_STOREI8_MEMBASE_IMM) || (ins2->opcode ==
OP_STORE_MEMBASE_IMM)) && (ins2->inst_imm == 0)) {
ins2->opcode =
store_membase_imm_to_store_membase_reg (ins2->opcode);
ins2->sreg1 = ins->dreg;
- } else if ((ins2->opcode ==
OP_STOREI1_MEMBASE_IMM) || (ins2->opcode == OP_STOREI2_MEMBASE_IMM)) {
+ } else if ((ins2->opcode ==
OP_STOREI1_MEMBASE_IMM) || (ins2->opcode == OP_STOREI2_MEMBASE_IMM) ||
(ins2->opcode == OP_STOREI8_MEMBASE_REG) || (ins2->opcode ==
OP_STORE_MEMBASE_REG)) {
/* Continue */
+ } else if (((ins2->opcode == OP_ICONST)
|| (ins2->opcode == OP_I8CONST)) && (ins2->dreg == ins->dreg) && (ins2->inst_c0
== 0)) {
+ ins2->opcode = OP_NOP;
+ ins2->dreg = ins2->sreg1 = -1;
+ /* Continue */
} else {
break;
}
}
}
break;
- case OP_MUL_IMM:
- /* remove unnecessary multiplication with 1 */
- if (ins->inst_imm == 1) {
- if (ins->dreg != ins->sreg1) {
- ins->opcode = OP_MOVE;
- } else {
- last_ins->next = ins->next;
- ins = ins->next;
- continue;
- }
- }
- break;
- case OP_COMPARE_IMM:
- case OP_LCOMPARE_IMM:
- /* OP_COMPARE_IMM (reg, 0)
- * -->
- * OP_AMD64_TEST_NULL (reg)
- */
- if (!ins->inst_imm)
- ins->opcode = OP_AMD64_TEST_NULL;
- break;
- case OP_ICOMPARE_IMM:
- if (!ins->inst_imm)
- ins->opcode = OP_X86_TEST_NULL;
- break;
case OP_AMD64_ICOMPARE_MEMBASE_IMM:
/*
* OP_STORE_MEMBASE_REG reg, offset(basereg)
@@ -1869,13 +2089,13 @@
if (last_ins && (last_ins->opcode ==
OP_STOREI4_MEMBASE_REG) &&
ins->inst_basereg == last_ins->inst_destbasereg &&
ins->inst_offset == last_ins->inst_offset) {
- ins->opcode = OP_ICOMPARE_IMM;
- ins->sreg1 = last_ins->sreg1;
+ ins->opcode = OP_ICOMPARE_IMM;
+ ins->sreg1 = last_ins->sreg1;
- /* check if we can remove cmp reg,0
with test null */
- if (!ins->inst_imm)
- ins->opcode = OP_X86_TEST_NULL;
- }
+ /* check if we can remove cmp reg,0 with test
null */
+ if (!ins->inst_imm)
+ ins->opcode = OP_X86_TEST_NULL;
+ }
break;
case OP_LOAD_MEMBASE:
@@ -2208,6 +2428,9 @@
mono_arch_lowering_pass (cfg, bb);
+ if (cfg->opt & MONO_OPT_PEEPHOLE)
+ peephole_pass_1 (cfg, bb);
+
mono_local_regalloc (cfg, bb);
}
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches