From 3f610de20fc15f7eb29dd2f9af5e34050e7d2877 Mon Sep 17 00:00:00 2001 From: Paolo Molaro Date: Wed, 7 Apr 2010 09:29:58 +0000 Subject: [PATCH] Wed Apr 7 11:28:42 CEST 2010 Paolo Molaro * method-to-ir.c: optimize array accesses from generic interfaces. svn path=/trunk/mono/; revision=154918 --- mono/mini/ChangeLog | 5 +++++ mono/mini/method-to-ir.c | 43 ++++++++++++++++++++++++++-------------- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/mono/mini/ChangeLog b/mono/mini/ChangeLog index 81e953847de74..be1c6aae6c06c 100755 --- a/mono/mini/ChangeLog +++ b/mono/mini/ChangeLog @@ -1,3 +1,8 @@ + +Wed Apr 7 11:28:42 CEST 2010 Paolo Molaro + + * method-to-ir.c: optimize array accesses from generic interfaces. + 2010-04-06 Zoltan Varga * mini-llvm.c: Update after the memset/memcpy intrinsics changes in LLVM SVN. diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 2adf4dfa8054d..aebed70ac4779 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -3731,7 +3731,7 @@ mini_field_access_needs_cctor_run (MonoCompile *cfg, MonoMethod *method, MonoVTa } static MonoInst* -mini_emit_ldelema_1_ins (MonoCompile *cfg, MonoClass *klass, MonoInst *arr, MonoInst *index) +mini_emit_ldelema_1_ins (MonoCompile *cfg, MonoClass *klass, MonoInst *arr, MonoInst *index, gboolean bcheck) { MonoInst *ins; guint32 size; @@ -3762,7 +3762,8 @@ mini_emit_ldelema_1_ins (MonoCompile *cfg, MonoClass *klass, MonoInst *arr, Mono } #endif - MONO_EMIT_BOUNDS_CHECK (cfg, array_reg, MonoArray, max_length, index2_reg); + if (bcheck) + MONO_EMIT_BOUNDS_CHECK (cfg, array_reg, MonoArray, max_length, index2_reg); #if defined(TARGET_X86) || defined(TARGET_AMD64) if (size == 1 || size == 2 || size == 4 || size == 8) { @@ -3856,7 +3857,7 @@ mini_emit_ldelema_ins (MonoCompile *cfg, MonoMethod *cmethod, MonoInst **sp, uns rank = mono_method_signature (cmethod)->param_count - (is_set? 1: 0); if (rank == 1) - return mini_emit_ldelema_1_ins (cfg, cmethod->klass->element_class, sp [0], sp [1]); + return mini_emit_ldelema_1_ins (cfg, cmethod->klass->element_class, sp [0], sp [1], TRUE); #ifndef MONO_ARCH_EMULATE_MUL_DIV /* emit_ldelema_2 depends on OP_LMUL */ @@ -3919,6 +3920,25 @@ should_insert_brekpoint (MonoMethod *method) { } } +/* optimize the simple GetGenericValueImpl/SetGenericValueImpl generic icalls */ +static MonoInst* +emit_array_generic_access (MonoCompile *cfg, MonoMethodSignature *fsig, MonoInst **args, int is_set) +{ + MonoInst *addr, *store, *load; + MonoClass *eklass = mono_class_from_mono_type (fsig->params [2]); + + /* the bounds check is already done by the callers */ + addr = mini_emit_ldelema_1_ins (cfg, eklass, args [0], args [1], FALSE); + if (is_set) { + EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, load, &eklass->byval_arg, args [2]->dreg, 0); + EMIT_NEW_STORE_MEMBASE_TYPE (cfg, store, &eklass->byval_arg, addr->dreg, 0, load->dreg); + } else { + EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, load, &eklass->byval_arg, addr->dreg, 0); + EMIT_NEW_STORE_MEMBASE_TYPE (cfg, store, &eklass->byval_arg, args [2]->dreg, 0, load->dreg); + } + return store; +} + static MonoInst* mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) { @@ -4007,6 +4027,8 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign } else return NULL; } else if (cmethod->klass == mono_defaults.array_class) { + if (strcmp (cmethod->name + 1, "etGenericValueImpl") == 0) + return emit_array_generic_access (cfg, fsig, args, *cmethod->name == 'S'); if (cmethod->name [0] != 'g') return NULL; @@ -4097,15 +4119,6 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign return (MonoInst*)mono_emit_method_call (cfg, fast_method, args, NULL); #endif - } else if (mini_class_is_system_array (cmethod->klass) && - strcmp (cmethod->name, "GetGenericValueImpl") == 0) { - MonoInst *addr, *store, *load; - MonoClass *eklass = mono_class_from_mono_type (fsig->params [1]); - - addr = mini_emit_ldelema_1_ins (cfg, eklass, args [0], args [1]); - EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, load, &eklass->byval_arg, addr->dreg, 0); - EMIT_NEW_STORE_MEMBASE_TYPE (cfg, store, &eklass->byval_arg, args [2]->dreg, 0, load->dreg); - return store; } else if (cmethod->klass->image == mono_defaults.corlib && (strcmp (cmethod->klass->name_space, "System.Threading") == 0) && (strcmp (cmethod->klass->name, "Interlocked") == 0)) { @@ -8489,7 +8502,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } readonly = FALSE; - ins = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1]); + ins = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1], TRUE); *sp++ = ins; ip += 5; break; @@ -8533,7 +8546,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b MONO_EMIT_BOUNDS_CHECK (cfg, array_reg, MonoArray, max_length, index_reg); EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, array_reg, offset); } else { - addr = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1]); + addr = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1], TRUE); EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, addr->dreg, 0); } *sp++ = ins; @@ -8597,7 +8610,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b MONO_EMIT_BOUNDS_CHECK (cfg, array_reg, MonoArray, max_length, index_reg); EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, array_reg, offset, sp [2]->dreg); } else { - addr = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1]); + addr = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1], TRUE); EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, addr->dreg, 0, sp [2]->dreg); } }