@@ -7076,6 +7076,21 @@ is_supported_tail_call (MonoCompile *cfg, MonoMethod *method, MonoMethod *cmetho
70767076 return supported_tail_call ;
70777077}
70787078
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+
70797094/*
70807095 * handle_ctor_call:
70817096 *
@@ -7851,7 +7866,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
78517866 CHECK_STACK_OVF (1 );
78527867 n = (* ip )- CEE_LDARG_0 ;
78537868 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+ }
78557874 ip ++ ;
78567875 * sp ++ = ins ;
78577876 break ;
@@ -7862,7 +7881,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
78627881 CHECK_STACK_OVF (1 );
78637882 n = (* ip )- CEE_LDLOC_0 ;
78647883 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+ }
78667889 ip ++ ;
78677890 * sp ++ = ins ;
78687891 break ;
@@ -7886,7 +7909,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
78867909 CHECK_STACK_OVF (1 );
78877910 n = ip [1 ];
78887911 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+ }
78907917 * sp ++ = ins ;
78917918 ip += 2 ;
78927919 break ;
@@ -7916,8 +7943,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
79167943 CHECK_STACK_OVF (1 );
79177944 n = ip [1 ];
79187945 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 ])) {
79217947 EMIT_NEW_LOCLOADA (cfg , ins , n );
79227948 } else {
79237949 EMIT_NEW_LOCLOAD (cfg , ins , n );
@@ -12428,7 +12454,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
1242812454 CHECK_OPSIZE (4 );
1242912455 n = read16 (ip + 2 );
1243012456 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+ }
1243212462 * sp ++ = ins ;
1243312463 ip += 4 ;
1243412464 break ;
@@ -12458,8 +12488,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
1245812488 CHECK_OPSIZE (4 );
1245912489 n = read16 (ip + 2 );
1246012490 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 ])) {
1246312492 EMIT_NEW_LOCLOADA (cfg , ins , n );
1246412493 } else {
1246512494 EMIT_NEW_LOCLOAD (cfg , ins , n );
0 commit comments