diff options
author | monojenkins <jo.shields+jenkins@xamarin.com> | 2018-03-07 17:54:59 +0300 |
---|---|---|
committer | Ludovic Henry <luhenry@microsoft.com> | 2018-03-07 17:54:59 +0300 |
commit | 30441ea0ac8fa090d8fb88ad5ed79b4d84212a3b (patch) | |
tree | 97a80a5862321f8231167f8e3e81e3b1cf428ccb | |
parent | 835a98d855921868c27d6672814cc1d0e44f32fd (diff) |
* Generalize commit 0c6932a985175a5cf0cbc59ffd3af4abf3db248e to support LDARG{0|1|2|3}, LDLOC{0|1|2|3}, LDARGS, LDLOCS, LDARG and LDLOC instead of LDLOC and LDLOCS. Improves generated code similar to issue #60945 (#7444)
-rw-r--r-- | mono/mini/method-to-ir.c | 45 |
1 files changed, 37 insertions, 8 deletions
diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index c9eab068478..3185a203fe8 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -7066,6 +7066,21 @@ is_supported_tail_call (MonoCompile *cfg, MonoMethod *method, MonoMethod *cmetho } /* + * is_adressable_valuetype_load + * + * 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 + */ +static gboolean +is_adressable_valuetype_load (MonoCompile* cfg, guint8* ip, MonoType* ldtype) +{ + /* Avoid loading a struct just to load one of its fields */ + gboolean is_load_instruction = (*ip == CEE_LDFLD); + gboolean is_in_previous_bb = ip_in_bb(cfg, cfg->cbb, ip); + gboolean is_struct = MONO_TYPE_ISSTRUCT(ldtype); + return is_load_instruction && is_in_previous_bb && is_struct; +} + +/* * handle_ctor_call: * * Handle calls made to ctors from NEWOBJ opcodes. @@ -7837,7 +7852,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b CHECK_STACK_OVF (1); n = (*ip)-CEE_LDARG_0; CHECK_ARG (n); - EMIT_NEW_ARGLOAD (cfg, ins, n); + if (is_adressable_valuetype_load (cfg, ip + 1, cfg->arg_types[n])) { + EMIT_NEW_ARGLOADA (cfg, ins, n); + } else { + EMIT_NEW_ARGLOAD (cfg, ins, n); + } ip++; *sp++ = ins; break; @@ -7848,7 +7867,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b CHECK_STACK_OVF (1); n = (*ip)-CEE_LDLOC_0; CHECK_LOCAL (n); - EMIT_NEW_LOCLOAD (cfg, ins, n); + if (is_adressable_valuetype_load (cfg, ip + 1, header->locals[n])) { + EMIT_NEW_LOCLOADA (cfg, ins, n); + } else { + EMIT_NEW_LOCLOAD (cfg, ins, n); + } ip++; *sp++ = ins; break; @@ -7872,7 +7895,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b CHECK_STACK_OVF (1); n = ip [1]; CHECK_ARG (n); - EMIT_NEW_ARGLOAD (cfg, ins, n); + if (is_adressable_valuetype_load (cfg, ip + 2, cfg->arg_types[n])) { + EMIT_NEW_ARGLOADA (cfg, ins, n); + } else { + EMIT_NEW_ARGLOAD (cfg, ins, n); + } *sp++ = ins; ip += 2; break; @@ -7902,8 +7929,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b CHECK_STACK_OVF (1); n = ip [1]; CHECK_LOCAL (n); - if ((ip [2] == CEE_LDFLD) && ip_in_bb (cfg, cfg->cbb, ip + 2) && MONO_TYPE_ISSTRUCT (header->locals [n])) { - /* Avoid loading a struct just to load one of its fields */ + if (is_adressable_valuetype_load (cfg, ip + 2, header->locals[n])) { EMIT_NEW_LOCLOADA (cfg, ins, n); } else { EMIT_NEW_LOCLOAD (cfg, ins, n); @@ -12365,7 +12391,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b CHECK_OPSIZE (4); n = read16 (ip + 2); CHECK_ARG (n); - EMIT_NEW_ARGLOAD (cfg, ins, n); + if (is_adressable_valuetype_load (cfg, ip + 4, cfg->arg_types[n])) { + EMIT_NEW_ARGLOADA (cfg, ins, n); + } else { + EMIT_NEW_ARGLOAD (cfg, ins, n); + } *sp++ = ins; ip += 4; break; @@ -12395,8 +12425,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b CHECK_OPSIZE (4); n = read16 (ip + 2); CHECK_LOCAL (n); - if ((ip [4] == CEE_LDFLD) && ip_in_bb (cfg, cfg->cbb, ip + 4) && header->locals [n]->type == MONO_TYPE_VALUETYPE) { - /* Avoid loading a struct just to load one of its fields */ + if (is_adressable_valuetype_load (cfg, ip + 4, header->locals[n])) { EMIT_NEW_LOCLOADA (cfg, ins, n); } else { EMIT_NEW_LOCLOAD (cfg, ins, n); |