From: Egor Bogatov Date: Fri, 12 Feb 2021 15:10:34 +0000 (+0300) Subject: [Mono] Fix EnumCompareTo for small integers (#48192) X-Git-Tag: submit/tizen/20210909.063632~3276 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9a946c701d40486e8eae1441620a2e5c7a22fa96;p=platform%2Fupstream%2Fdotnet%2Fruntime.git [Mono] Fix EnumCompareTo for small integers (#48192) --- diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index ac50ed6..8446da4 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -2383,34 +2383,46 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas // Save arguments store_local (td, localb); store_local (td, locala); - // (a > b) load_local (td, locala); load_local (td, localb); - if (is_unsigned) - interp_add_ins (td, is_i8 ? MINT_CGT_UN_I8 : MINT_CGT_UN_I4); - else - interp_add_ins (td, is_i8 ? MINT_CGT_I8 : MINT_CGT_I4); - td->sp -= 2; - interp_ins_set_sregs2 (td->last_ins, td->sp [0].local, td->sp [1].local); - push_simple_type (td, STACK_TYPE_I4); - interp_ins_set_dreg (td->last_ins, td->sp [-1].local); - // (a < b) - load_local (td, locala); - load_local (td, localb); - if (is_unsigned) - interp_add_ins (td, is_i8 ? MINT_CLT_UN_I8 : MINT_CLT_UN_I4); + + if (t->type >= MONO_TYPE_BOOLEAN && t->type <= MONO_TYPE_U2) + { + interp_add_ins (td, MINT_SUB_I4); + td->sp -= 2; + interp_ins_set_sregs2 (td->last_ins, td->sp [0].local, td->sp [1].local); + push_simple_type (td, STACK_TYPE_I4); + interp_ins_set_dreg (td->last_ins, td->sp [-1].local); + } else - interp_add_ins (td, is_i8 ? MINT_CLT_I8 : MINT_CLT_I4); - td->sp -= 2; - interp_ins_set_sregs2 (td->last_ins, td->sp [0].local, td->sp [1].local); - push_simple_type (td, STACK_TYPE_I4); - interp_ins_set_dreg (td->last_ins, td->sp [-1].local); - // (a > b) - (a < b) - interp_add_ins (td, MINT_SUB_I4); - td->sp -= 2; - interp_ins_set_sregs2 (td->last_ins, td->sp [0].local, td->sp [1].local); - push_simple_type (td, STACK_TYPE_I4); - interp_ins_set_dreg (td->last_ins, td->sp [-1].local); + { + // (a > b) + if (is_unsigned) + interp_add_ins (td, is_i8 ? MINT_CGT_UN_I8 : MINT_CGT_UN_I4); + else + interp_add_ins (td, is_i8 ? MINT_CGT_I8 : MINT_CGT_I4); + td->sp -= 2; + interp_ins_set_sregs2 (td->last_ins, td->sp [0].local, td->sp [1].local); + push_simple_type (td, STACK_TYPE_I4); + interp_ins_set_dreg (td->last_ins, td->sp [-1].local); + // (a < b) + load_local (td, locala); + load_local (td, localb); + if (is_unsigned) + interp_add_ins (td, is_i8 ? MINT_CLT_UN_I8 : MINT_CLT_UN_I4); + else + interp_add_ins (td, is_i8 ? MINT_CLT_I8 : MINT_CLT_I4); + td->sp -= 2; + interp_ins_set_sregs2 (td->last_ins, td->sp [0].local, td->sp [1].local); + push_simple_type (td, STACK_TYPE_I4); + interp_ins_set_dreg (td->last_ins, td->sp [-1].local); + // (a > b) - (a < b) + interp_add_ins (td, MINT_SUB_I4); + td->sp -= 2; + interp_ins_set_sregs2 (td->last_ins, td->sp [0].local, td->sp [1].local); + push_simple_type (td, STACK_TYPE_I4); + interp_ins_set_dreg (td->last_ins, td->sp [-1].local); + } td->ip += 5; return TRUE; } else { diff --git a/src/mono/mono/mini/intrinsics.c b/src/mono/mono/mini/intrinsics.c index 52a01b1..13677c2 100644 --- a/src/mono/mono/mini/intrinsics.c +++ b/src/mono/mono/mini/intrinsics.c @@ -632,11 +632,19 @@ emit_jit_helpers_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSi reg2 = alloc_ireg (cfg); dreg = alloc_ireg (cfg); - EMIT_NEW_BIALU (cfg, ins, cmp_op, -1, args [0]->dreg, args [1]->dreg); - EMIT_NEW_UNALU (cfg, ins, cgt_op, reg1, -1); - EMIT_NEW_BIALU (cfg, ins, cmp_op, -1, args [0]->dreg, args [1]->dreg); - EMIT_NEW_UNALU (cfg, ins, clt_op, reg2, -1); - EMIT_NEW_BIALU (cfg, ins, OP_ISUB, dreg, reg1, reg2); + if (t->type >= MONO_TYPE_BOOLEAN && t->type <= MONO_TYPE_U2) + { + // Use "a - b" for small types (smaller than Int32) + EMIT_NEW_BIALU (cfg, ins, OP_ISUB, dreg, args [0]->dreg, args [1]->dreg); + } + else + { + EMIT_NEW_BIALU (cfg, ins, cmp_op, -1, args [0]->dreg, args [1]->dreg); + EMIT_NEW_UNALU (cfg, ins, cgt_op, reg1, -1); + EMIT_NEW_BIALU (cfg, ins, cmp_op, -1, args [0]->dreg, args [1]->dreg); + EMIT_NEW_UNALU (cfg, ins, clt_op, reg2, -1); + EMIT_NEW_BIALU (cfg, ins, OP_ISUB, dreg, reg1, reg2); + } } return ins; }