[mono][interp] Lower div.un to shr.un.imm (#83498)
authorVlad Brezae <brezaevlad@gmail.com>
Thu, 16 Mar 2023 13:05:44 +0000 (15:05 +0200)
committerGitHub <noreply@github.com>
Thu, 16 Mar 2023 13:05:44 +0000 (15:05 +0200)
* [mono][interp] Remove redundant opcode

Generate sub opcode instead which is detected by other optimizations.

* [mono][interp] Lower div.un to shr.un

src/mono/mono/mini/interp/interp.c
src/mono/mono/mini/interp/jiterpreter.c
src/mono/mono/mini/interp/mintops.def
src/mono/mono/mini/interp/transform.c
src/mono/wasm/runtime/jiterpreter-trace-generator.ts

index 563e58a..45b9243 100644 (file)
@@ -5963,11 +5963,6 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK;
                        ip += 5;
                        MINT_IN_BREAK;
                }
-               MINT_IN_CASE(MINT_INTRINS_UNSAFE_BYTE_OFFSET) {
-                       LOCAL_VAR (ip [1], mono_u) = LOCAL_VAR (ip [3], guint8*) - LOCAL_VAR (ip [2], guint8*);
-                       ip += 4;
-                       MINT_IN_BREAK;
-               }
                MINT_IN_CASE(MINT_INTRINS_RUNTIMEHELPERS_OBJECT_HAS_COMPONENT_SIZE) {
                        MonoObject *obj = LOCAL_VAR (ip [2], MonoObject*);
                        LOCAL_VAR (ip [1], gint32) = (obj->vtable->flags & MONO_VT_FLAG_ARRAY_OR_STRING) != 0;
index 2f86775..7401b1d 100644 (file)
@@ -666,7 +666,6 @@ jiterp_should_abort_trace (InterpInst *ins, gboolean *inside_branch_block)
                case MINT_GETITEM_SPAN:
                case MINT_GETITEM_LOCALSPAN:
                case MINT_INTRINS_SPAN_CTOR:
-               case MINT_INTRINS_UNSAFE_BYTE_OFFSET:
                case MINT_INTRINS_GET_TYPE:
                case MINT_INTRINS_MEMORYMARSHAL_GETARRAYDATAREF:
                case MINT_CASTCLASS:
index 750a6e5..a0418ad 100644 (file)
@@ -824,7 +824,6 @@ OPDEF(MINT_INTRINS_GET_HASHCODE, "intrins_get_hashcode", 3, 1, 1, MintOpNoArgs)
 OPDEF(MINT_INTRINS_TRY_GET_HASHCODE, "intrins_try_get_hashcode", 3, 1, 1, MintOpNoArgs)
 OPDEF(MINT_INTRINS_GET_TYPE, "intrins_get_type", 3, 1, 1, MintOpNoArgs)
 OPDEF(MINT_INTRINS_SPAN_CTOR, "intrins_span_ctor", 4, 1, 2, MintOpNoArgs)
-OPDEF(MINT_INTRINS_UNSAFE_BYTE_OFFSET, "intrins_unsafe_byte_offset", 4, 1, 2, MintOpNoArgs)
 OPDEF(MINT_INTRINS_RUNTIMEHELPERS_OBJECT_HAS_COMPONENT_SIZE, "intrins_runtimehelpers_object_has_component_size", 3, 1, 1, MintOpNoArgs)
 OPDEF(MINT_INTRINS_CLEAR_WITH_REFERENCES, "intrin_clear_with_references", 3, 0, 2, MintOpNoArgs)
 OPDEF(MINT_INTRINS_MARVIN_BLOCK, "intrins_marvin_block", 3, 0, 2, MintOpNoArgs)
index db02d71..f81f417 100644 (file)
@@ -2119,7 +2119,17 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas
                } else if (!strcmp (tm, "AreSame")) {
                        *op = MINT_CEQ_P;
                } else if (!strcmp (tm, "ByteOffset")) {
-                       *op = MINT_INTRINS_UNSAFE_BYTE_OFFSET;
+#if SIZEOF_VOID_P == 4
+                       interp_add_ins (td, MINT_SUB_I4);
+#else
+                       interp_add_ins (td, MINT_SUB_I8);
+#endif
+                       td->sp -= 2;
+                       interp_ins_set_sregs2 (td->last_ins, td->sp [1].local, td->sp [0].local);
+                       push_simple_type (td, STACK_TYPE_I);
+                       interp_ins_set_dreg (td->last_ins, td->sp [-1].local);
+                       td->ip += 5;
+                       return TRUE;
                } else if (!strcmp (tm, "Unbox")) {
                        MonoGenericContext *ctx = mono_method_get_context (target_method);
                        g_assert (ctx);
@@ -9873,6 +9883,39 @@ interp_super_instructions (TransformData *td)
                                                dump_interp_inst (new_inst);
                                        }
                                }
+                       } else if (opcode == MINT_DIV_UN_I4 || opcode == MINT_DIV_UN_I8) {
+                               // ldc + div.un -> shr.imm
+                               int sreg_imm = ins->sregs [1];
+                               InterpInst *def = td->locals [sreg_imm].def;
+                               if (def != NULL && td->local_ref_count [sreg_imm] == 1) {
+                                       int power2 = -1;
+                                       if (MINT_IS_LDC_I4 (def->opcode)) {
+                                               guint32 ct = interp_get_const_from_ldc_i4 (def);
+                                               power2 = mono_is_power_of_two ((guint32)ct);
+                                       } else if (MINT_IS_LDC_I8 (def->opcode)) {
+                                               guint64 ct = interp_get_const_from_ldc_i8 (def);
+                                               if (ct < G_MAXUINT32)
+                                                       power2 = mono_is_power_of_two ((guint32)ct);
+                                       }
+                                       if (power2 > 0) {
+                                               InterpInst *new_inst;
+                                               if (opcode == MINT_DIV_UN_I4)
+                                                       new_inst = interp_insert_ins (td, ins, MINT_SHR_UN_I4_IMM);
+                                               else
+                                                       new_inst = interp_insert_ins (td, ins, MINT_SHR_UN_I8_IMM);
+                                               new_inst->dreg = ins->dreg;
+                                               new_inst->sregs [0] = ins->sregs [0];
+                                               new_inst->data [0] = power2;
+
+                                               interp_clear_ins (def);
+                                               interp_clear_ins (ins);
+                                               local_ref_count [sreg_imm]--;
+                                               if (td->verbose_level) {
+                                                       g_print ("lower div.un: ");
+                                                       dump_interp_inst (new_inst);
+                                               }
+                                       }
+                               }
                        } else if (MINT_IS_LDIND_INT (opcode)) {
                                int sreg_base = ins->sregs [0];
                                InterpInst *def = td->locals [sreg_base].def;
index 62e6065..b6c9790 100644 (file)
@@ -613,13 +613,6 @@ export function generate_wasm_body (
                 builder.callImport("ldtsflda");
                 break;
             }
-            case MintOpcode.MINT_INTRINS_UNSAFE_BYTE_OFFSET:
-                builder.local("pLocals");
-                append_ldloc(builder, getArgU16(ip, 3), WasmOpcode.i32_load);
-                append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.i32_load);
-                builder.appendU8(WasmOpcode.i32_sub);
-                append_stloc_tail(builder, getArgU16(ip, 1), WasmOpcode.i32_store);
-                break;
             case MintOpcode.MINT_INTRINS_GET_TYPE:
                 builder.block();
                 // dest, src