@@ -7076,6 +7076,21 @@ is_supported_tail_call (MonoCompile *cfg, MonoMethod *method, MonoMethod *cmetho
7076
7076
return supported_tail_call ;
7077
7077
}
7078
7078
7079
+ /*
7080
+ * is_adressable_valuetype_load
7081
+ *
7082
+ * Returns true if a previous load can be done without doing an extra copy, given the new instruction ip and the type of the object being loaded ldtype
7083
+ */
7084
+ static gboolean
7085
+ is_adressable_valuetype_load (MonoCompile * cfg , guint8 * ip , MonoType * ldtype )
7086
+ {
7087
+ /* Avoid loading a struct just to load one of its fields */
7088
+ gboolean is_load_instruction = (* ip == CEE_LDFLD );
7089
+ gboolean is_in_previous_bb = ip_in_bb (cfg , cfg -> cbb , ip );
7090
+ gboolean is_struct = MONO_TYPE_ISSTRUCT (ldtype );
7091
+ return is_load_instruction && is_in_previous_bb && is_struct ;
7092
+ }
7093
+
7079
7094
/*
7080
7095
* handle_ctor_call:
7081
7096
*
@@ -7851,7 +7866,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
7851
7866
CHECK_STACK_OVF (1 );
7852
7867
n = (* ip )- CEE_LDARG_0 ;
7853
7868
CHECK_ARG (n );
7854
- EMIT_NEW_ARGLOAD (cfg , ins , n );
7869
+ if (is_adressable_valuetype_load (cfg , ip + 1 , cfg -> arg_types [n ])) {
7870
+ EMIT_NEW_ARGLOADA (cfg , ins , n );
7871
+ } else {
7872
+ EMIT_NEW_ARGLOAD (cfg , ins , n );
7873
+ }
7855
7874
ip ++ ;
7856
7875
* sp ++ = ins ;
7857
7876
break ;
@@ -7862,7 +7881,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
7862
7881
CHECK_STACK_OVF (1 );
7863
7882
n = (* ip )- CEE_LDLOC_0 ;
7864
7883
CHECK_LOCAL (n );
7865
- EMIT_NEW_LOCLOAD (cfg , ins , n );
7884
+ if (is_adressable_valuetype_load (cfg , ip + 1 , header -> locals [n ])) {
7885
+ EMIT_NEW_LOCLOADA (cfg , ins , n );
7886
+ } else {
7887
+ EMIT_NEW_LOCLOAD (cfg , ins , n );
7888
+ }
7866
7889
ip ++ ;
7867
7890
* sp ++ = ins ;
7868
7891
break ;
@@ -7886,7 +7909,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
7886
7909
CHECK_STACK_OVF (1 );
7887
7910
n = ip [1 ];
7888
7911
CHECK_ARG (n );
7889
- EMIT_NEW_ARGLOAD (cfg , ins , n );
7912
+ if (is_adressable_valuetype_load (cfg , ip + 2 , cfg -> arg_types [n ])) {
7913
+ EMIT_NEW_ARGLOADA (cfg , ins , n );
7914
+ } else {
7915
+ EMIT_NEW_ARGLOAD (cfg , ins , n );
7916
+ }
7890
7917
* sp ++ = ins ;
7891
7918
ip += 2 ;
7892
7919
break ;
@@ -7916,8 +7943,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
7916
7943
CHECK_STACK_OVF (1 );
7917
7944
n = ip [1 ];
7918
7945
CHECK_LOCAL (n );
7919
- if ((ip [2 ] == CEE_LDFLD ) && ip_in_bb (cfg , cfg -> cbb , ip + 2 ) && MONO_TYPE_ISSTRUCT (header -> locals [n ])) {
7920
- /* Avoid loading a struct just to load one of its fields */
7946
+ if (is_adressable_valuetype_load (cfg , ip + 2 , header -> locals [n ])) {
7921
7947
EMIT_NEW_LOCLOADA (cfg , ins , n );
7922
7948
} else {
7923
7949
EMIT_NEW_LOCLOAD (cfg , ins , n );
@@ -12428,7 +12454,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
12428
12454
CHECK_OPSIZE (4 );
12429
12455
n = read16 (ip + 2 );
12430
12456
CHECK_ARG (n );
12431
- EMIT_NEW_ARGLOAD (cfg , ins , n );
12457
+ if (is_adressable_valuetype_load (cfg , ip + 4 , cfg -> arg_types [n ])) {
12458
+ EMIT_NEW_ARGLOADA (cfg , ins , n );
12459
+ } else {
12460
+ EMIT_NEW_ARGLOAD (cfg , ins , n );
12461
+ }
12432
12462
* sp ++ = ins ;
12433
12463
ip += 4 ;
12434
12464
break ;
@@ -12458,8 +12488,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
12458
12488
CHECK_OPSIZE (4 );
12459
12489
n = read16 (ip + 2 );
12460
12490
CHECK_LOCAL (n );
12461
- if ((ip [4 ] == CEE_LDFLD ) && ip_in_bb (cfg , cfg -> cbb , ip + 4 ) && MONO_TYPE_ISSTRUCT (header -> locals [n ])) {
12462
- /* Avoid loading a struct just to load one of its fields */
12491
+ if (is_adressable_valuetype_load (cfg , ip + 4 , header -> locals [n ])) {
12463
12492
EMIT_NEW_LOCLOADA (cfg , ins , n );
12464
12493
} else {
12465
12494
EMIT_NEW_LOCLOAD (cfg , ins , n );
0 commit comments