Author: zoltan
Date: 2008-01-18 09:46:06 -0500 (Fri, 18 Jan 2008)
New Revision: 93260

Modified:
   trunk/mono/mono/mini/ChangeLog
   trunk/mono/mono/mini/mini-amd64.c
Log:
2008-01-18  Zoltan Varga  <[EMAIL PROTECTED]>

        * mini-amd64.c (mono_arch_call_opcode): Keep assignments to the arg 
registers
        in order if possible.
        (mono_arch_emit_prolog): Optimize assignments to arg registers in the 
first
        bblock, since the arguments are still in their original registers.


Modified: trunk/mono/mono/mini/ChangeLog
===================================================================
--- trunk/mono/mono/mini/ChangeLog      2008-01-18 14:31:43 UTC (rev 93259)
+++ trunk/mono/mono/mini/ChangeLog      2008-01-18 14:46:06 UTC (rev 93260)
@@ -1,7 +1,12 @@
 2008-01-18  Zoltan Varga  <[EMAIL PROTECTED]>
 
-       * mini.c (type_from_op): Calling add.ovf on floats in not valid IL code.
+       * mini-amd64.c (mono_arch_call_opcode): Keep assignments to the arg 
registers
+       in order if possible.
+       (mono_arch_emit_prolog): Optimize assignments to arg registers in the 
first
+       bblock, since the arguments are still in their original registers.
 
+       * mini.c (type_from_op): Calling add.ovf on floats is not valid IL code.
+
 2008-01-17  Zoltan Varga  <[EMAIL PROTECTED]>
 
        * mini.c (mono_method_to_ir): Use the no-spilling optimization for 
CEE_CALLI

Modified: trunk/mono/mono/mini/mini-amd64.c
===================================================================
--- trunk/mono/mono/mini/mini-amd64.c   2008-01-18 14:31:43 UTC (rev 93259)
+++ trunk/mono/mono/mini/mini-amd64.c   2008-01-18 14:46:06 UTC (rev 93260)
@@ -1300,7 +1300,11 @@
                        arg->cil_code = in->cil_code;
                        arg->inst_left = in;
                        arg->type = in->type;
-                       MONO_INST_LIST_ADD (&arg->node, &call->out_args);
+                       if (!cinfo->stack_usage)
+                               /* Keep the assignments to the arg registers in 
order if possible */
+                               MONO_INST_LIST_ADD_TAIL (&arg->node, 
&call->out_args);
+                       else
+                               MONO_INST_LIST_ADD (&arg->node, 
&call->out_args);
 
                        if ((i >= sig->hasthis) && 
(MONO_TYPE_ISSTRUCT(sig->params [i - sig->hasthis]))) {
                                guint32 align;
@@ -4365,11 +4369,12 @@
        MonoMethod *method = cfg->method;
        MonoBasicBlock *bb;
        MonoMethodSignature *sig;
-       MonoInst *inst;
+       MonoInst *ins;
        int alloc_size, pos, max_offset, i, quad;
        guint8 *code;
        CallInfo *cinfo;
        gint32 lmf_offset = cfg->arch.lmf_offset;
+       gboolean args_clobbered = FALSE;
 
        cfg->code_size =  MAX (((MonoMethodNormal *)method)->header->code_size 
* 4, 10240);
 
@@ -4491,7 +4496,6 @@
        max_offset = 0;
        if (cfg->opt & MONO_OPT_BRANCH) {
                for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
-                       MonoInst *ins;
                        bb->max_offset = max_offset;
 
                        if (cfg->prof_options & MONO_PROFILE_COVERAGE)
@@ -4526,8 +4530,9 @@
                ArgInfo *ainfo = cinfo->args + i;
                gint32 stack_offset;
                MonoType *arg_type;
-               inst = cfg->args [i];
 
+               ins = cfg->args [i];
+
                if (sig->hasthis && (i == 0))
                        arg_type = &mono_defaults.object_class->byval_arg;
                else
@@ -4536,7 +4541,7 @@
                stack_offset = ainfo->offset + ARGS_OFFSET;
 
                /* Save volatile arguments to the stack */
-               if (inst->opcode != OP_REGVAR) {
+               if (ins->opcode != OP_REGVAR) {
                        switch (ainfo->storage) {
                        case ArgInIReg: {
                                guint32 size = 8;
@@ -4552,26 +4557,26 @@
                                else
                                        size = 8;
                                */
-                               amd64_mov_membase_reg (code, 
inst->inst_basereg, inst->inst_offset, ainfo->reg, size);
+                               amd64_mov_membase_reg (code, ins->inst_basereg, 
ins->inst_offset, ainfo->reg, size);
                                break;
                        }
                        case ArgInFloatSSEReg:
-                               amd64_movss_membase_reg (code, 
inst->inst_basereg, inst->inst_offset, ainfo->reg);
+                               amd64_movss_membase_reg (code, 
ins->inst_basereg, ins->inst_offset, ainfo->reg);
                                break;
                        case ArgInDoubleSSEReg:
-                               amd64_movsd_membase_reg (code, 
inst->inst_basereg, inst->inst_offset, ainfo->reg);
+                               amd64_movsd_membase_reg (code, 
ins->inst_basereg, ins->inst_offset, ainfo->reg);
                                break;
                        case ArgValuetypeInReg:
                                for (quad = 0; quad < 2; quad ++) {
                                        switch (ainfo->pair_storage [quad]) {
                                        case ArgInIReg:
-                                               amd64_mov_membase_reg (code, 
inst->inst_basereg, inst->inst_offset + (quad * sizeof (gpointer)), 
ainfo->pair_regs [quad], sizeof (gpointer));
+                                               amd64_mov_membase_reg (code, 
ins->inst_basereg, ins->inst_offset + (quad * sizeof (gpointer)), 
ainfo->pair_regs [quad], sizeof (gpointer));
                                                break;
                                        case ArgInFloatSSEReg:
-                                               amd64_movss_membase_reg (code, 
inst->inst_basereg, inst->inst_offset + (quad * sizeof (gpointer)), 
ainfo->pair_regs [quad]);
+                                               amd64_movss_membase_reg (code, 
ins->inst_basereg, ins->inst_offset + (quad * sizeof (gpointer)), 
ainfo->pair_regs [quad]);
                                                break;
                                        case ArgInDoubleSSEReg:
-                                               amd64_movsd_membase_reg (code, 
inst->inst_basereg, inst->inst_offset + (quad * sizeof (gpointer)), 
ainfo->pair_regs [quad]);
+                                               amd64_movsd_membase_reg (code, 
ins->inst_basereg, ins->inst_offset + (quad * sizeof (gpointer)), 
ainfo->pair_regs [quad]);
                                                break;
                                        case ArgNone:
                                                break;
@@ -4583,16 +4588,14 @@
                        default:
                                break;
                        }
-               }
-
-               if (inst->opcode == OP_REGVAR) {
+               } else {
                        /* Argument allocated to (non-volatile) register */
                        switch (ainfo->storage) {
                        case ArgInIReg:
-                               amd64_mov_reg_reg (code, inst->dreg, 
ainfo->reg, 8);
+                               amd64_mov_reg_reg (code, ins->dreg, ainfo->reg, 
8);
                                break;
                        case ArgOnStack:
-                               amd64_mov_reg_membase (code, inst->dreg, 
AMD64_RBP, ARGS_OFFSET + ainfo->offset, 8);
+                               amd64_mov_reg_membase (code, ins->dreg, 
AMD64_RBP, ARGS_OFFSET + ainfo->offset, 8);
                                break;
                        default:
                                g_assert_not_reached ();
@@ -4604,6 +4607,8 @@
        if (method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
                guint64 domain = (guint64)cfg->domain;
 
+               args_clobbered = TRUE;
+
                /* 
                 * The call might clobber argument registers, but they are 
already
                 * saved to the stack/global regs.
@@ -4667,6 +4672,7 @@
                                 * The call might clobber argument registers, 
but they are already
                                 * saved to the stack/global regs.
                                 */
+                               args_clobbered = TRUE;
                                code = emit_call (cfg, code, 
MONO_PATCH_INFO_INTERNAL_METHOD, 
                                                                  
(gpointer)"mono_get_lmf_addr");               
                        }
@@ -4682,9 +4688,67 @@
                }
        }
 
-       if (mono_jit_trace_calls != NULL && mono_trace_eval (method))
+       if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
+               args_clobbered = TRUE;
                code = mono_arch_instrument_prolog (cfg, 
mono_trace_enter_method, code, TRUE);
+       }
 
+       /*
+        * Optimize the common case of the first bblock making a call with the 
same
+        * arguments as the method. This works because the arguments are still 
in their
+        * original argument registers.
+        * FIXME: Generalize this
+        */
+       if (!args_clobbered) {
+               MonoBasicBlock *first_bb = cfg->bb_entry;
+               MonoInst *next;
+
+               next = mono_inst_list_first (&first_bb->ins_list);
+               if (!next && first_bb->next_bb) {
+                       first_bb = first_bb->next_bb;
+                       next = mono_inst_list_first (&first_bb->ins_list);
+               }
+
+               if (first_bb->in_count > 1)
+                       next = NULL;
+
+               for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
+                       ArgInfo *ainfo = cinfo->args + i;
+                       gboolean match = FALSE;
+                       
+                       ins = cfg->args [i];
+                       if (ins->opcode != OP_REGVAR) {
+                               switch (ainfo->storage) {
+                               case ArgInIReg: {
+                                       if (next->opcode == OP_LOAD_MEMBASE && 
next->inst_basereg == ins->inst_basereg && next->inst_offset == 
ins->inst_offset && next->dreg == ainfo->reg) {
+                                               NULLIFY_INS (next);
+                                               match = TRUE;
+                                       }
+                                       break;
+                               }
+                               default:
+                                       break;
+                               }
+                       } else {
+                               /* Argument allocated to (non-volatile) 
register */
+                               switch (ainfo->storage) {
+                               case ArgInIReg:
+                                       if (next->opcode == OP_MOVE && 
next->sreg1 == ins->dreg && next->dreg == ainfo->reg) {
+                                               NULLIFY_INS (next);
+                                               match = TRUE;
+                                       }
+                                       break;
+                               default:
+                                       break;
+                               }
+                       }
+
+                       if (!match)
+                               break;
+                       next = mono_inst_list_next (&next->node, 
&first_bb->ins_list);
+               }
+       }
+
        cfg->code_len = code - cfg->native_code;
 
        g_assert (cfg->code_len < cfg->code_size);

_______________________________________________
Mono-patches maillist  -  Mono-patches@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to