[mono][llvm] Add a fastpath to calling mini_init_method_rgctx (). (#84226)
authorZoltan Varga <vargaz@gmail.com>
Mon, 3 Apr 2023 15:22:06 +0000 (11:22 -0400)
committerGitHub <noreply@github.com>
Mon, 3 Apr 2023 15:22:06 +0000 (11:22 -0400)
* [mono][llvm] Add a fastpath to calling mini_init_method_rgctx ().

* Add arm64 JIT support.

src/mono/mono/mini/cpu-arm64.mdesc
src/mono/mono/mini/method-to-ir.c
src/mono/mono/mini/mini-arm64.c
src/mono/mono/mini/mini-arm64.h
src/mono/mono/mini/mini-llvm.c
src/mono/mono/mini/mini-ops.h
src/mono/mono/mini/mini.c
src/mono/mono/mini/mini.h

index 1b075a0926dcc20f6f420ae80eedb393ec738002..3981c544347783974ce271a8bce9f25d946cf7c1 100644 (file)
@@ -523,5 +523,6 @@ expand_r8: dest:x src1:f len:4
 
 generic_class_init: src1:a len:44 clob:c
 gc_safe_point: src1:i len:12 clob:c
+init_mrgctx: src1:a src2:i len:44 clob:c
 
 fill_prof_call_ctx: src1:i len:128
index e208a67669f65c830400a8fe413d3dbe8c52bbec..6578497e745008057e7f4109d2b8f283254b34a2 100644 (file)
@@ -6750,7 +6750,15 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        EMIT_NEW_PCONST (cfg, args [1], info);
 
                cfg->init_method_rgctx_ins_arg = args [1];
-               cfg->init_method_rgctx_ins = mono_emit_jit_icall (cfg, mini_init_method_rgctx, args);
+               if (COMPILE_LLVM (cfg) || cfg->backend->have_init_mrgctx) {
+                       MONO_INST_NEW (cfg, ins, OP_INIT_MRGCTX);
+                       ins->sreg1 = args [0]->dreg;
+                       ins->sreg2 = args [1]->dreg;
+                       MONO_ADD_INS (cfg->cbb, ins);
+                       cfg->init_method_rgctx_ins = ins;
+               } else {
+                       cfg->init_method_rgctx_ins = mono_emit_jit_icall (cfg, mini_init_method_rgctx, args);
+               }
        }
 
        if (cfg->gsharedvt && cfg->method == method) {
index 96822e9b9b4fa59a40e2836e894089967076c73f..dcdbafa631dd4addcc75afd234194c9443bb1f11 100644 (file)
@@ -5023,6 +5023,27 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        mono_arm_patch (jump, code, MONO_R_ARM64_CBZ);
                        break;
                }
+               case OP_INIT_MRGCTX: {
+                       int field_offset;
+                       guint8 *jump;
+
+                       field_offset = MONO_STRUCT_OFFSET (MonoMethodRuntimeGenericContext, entries);
+
+                       /* Load mrgxtx->entries */
+                       arm_ldrx (code, ARMREG_IP0, sreg1, field_offset);
+                       jump = code;
+                       arm_cbnzx (code, ARMREG_IP0, 0);
+
+                       /* Slowpath */
+                       g_assert (sreg1 == ARMREG_R0);
+                       if (sreg2 != ARMREG_R1)
+                               arm_movx (code, ARMREG_R1, sreg2);
+                       code = emit_call (cfg, code, MONO_PATCH_INFO_JIT_ICALL_ID,
+                                                         GUINT_TO_POINTER (MONO_JIT_ICALL_mini_init_method_rgctx));
+
+                       mono_arm_patch (jump, code, MONO_R_ARM64_CBZ);
+                       break;
+               }
 
                case OP_CHECK_THIS:
                        arm_ldrb (code, ARMREG_LR, sreg1, 0);
index 7dfe8eed08c069820915f260875c7576a998dd2b..7d8e24c3763df0612348c138c645578f3d2e4269 100644 (file)
@@ -179,6 +179,7 @@ typedef struct {
 #define MONO_ARCH_HAVE_DECOMPOSE_LONG_OPTS 1
 #define MONO_ARCH_FLOAT32_SUPPORTED 1
 #define MONO_ARCH_HAVE_INTERP_PINVOKE_TRAMP 1
+#define MONO_ARCH_HAVE_INIT_MRGCTX 1
 #define MONO_ARCH_LLVM_TARGET_LAYOUT "e-i64:64-i128:128-n32:64-S128"
 #ifdef TARGET_OSX
 #define MONO_ARCH_FORCE_FLOAT32 1
index 1d78c8dd81d825318fac0b25190590f84d13b142..93fde86ad77fe4c2f8180621e8a9362e40a46df9 100644 (file)
@@ -7415,6 +7415,52 @@ MONO_RESTORE_WARNING
                        break;
                }
 
+               case OP_INIT_MRGCTX: {
+                       LLVMValueRef val, cmp, callee;
+                       LLVMBasicBlockRef poll_bb, cont_bb;
+                       LLVMValueRef args [2];
+                       static LLVMTypeRef icall_sig;
+
+                       g_assert (cfg->compile_aot);
+
+                       /*
+                        * if (!((MonoMethodRuntimeGenericContext)->lhs)->entries)
+                        *   mini_init_method_rgctx (lhs, rhs);
+                        */
+
+                       LLVMValueRef offset = const_int32 (MONO_STRUCT_OFFSET (MonoMethodRuntimeGenericContext, entries));
+                       LLVMValueRef ptr = LLVMBuildAdd (builder, convert (ctx, lhs, IntPtrType ()), convert (ctx, offset, IntPtrType ()), "");
+
+                       val = emit_load (builder, IntPtrType (), convert (ctx, ptr, pointer_type (IntPtrType ())), "", TRUE);
+                       cmp = LLVMBuildICmp (builder, LLVMIntEQ, val, LLVMConstNull (LLVMTypeOf (val)), "");
+                       poll_bb = gen_bb (ctx, "POLL_BB");
+                       cont_bb = gen_bb (ctx, "CONT_BB");
+
+                       args [0] = cmp;
+                       args [1] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
+                       cmp = call_intrins (ctx, INTRINS_EXPECT_I1, args, "");
+
+                       mono_llvm_build_weighted_branch (builder, cmp, poll_bb, cont_bb, 1, 1000);
+
+                       ctx->builder = builder = create_builder (ctx);
+                       LLVMPositionBuilderAtEnd (builder, poll_bb);
+
+                       if (!icall_sig)
+                               icall_sig = LLVMFunctionType2 (LLVMVoidType (), IntPtrType (), IntPtrType (), FALSE);
+
+                       args [0] = convert (ctx, lhs, IntPtrType ());
+                       args [1] = convert (ctx, rhs, IntPtrType ());
+
+                       callee = get_callee (ctx, icall_sig, MONO_PATCH_INFO_JIT_ICALL_ID, GUINT_TO_POINTER (MONO_JIT_ICALL_mini_init_method_rgctx));
+                       LLVMBuildCall2 (builder, icall_sig, callee, args, 2, "");
+                       LLVMBuildBr (builder, cont_bb);
+
+                       ctx->builder = builder = create_builder (ctx);
+                       LLVMPositionBuilderAtEnd (builder, cont_bb);
+                       ctx->bblocks [bb->block_num].end_bblock = cont_bb;
+                       break;
+               }
+
                        /*
                         * Overflow opcodes.
                         */
index 162711201ad14236c1867370f1df979a49aa310e..ece6964839c5ab87f8bc3b17e2f6a4bf10ea38c8 100644 (file)
@@ -1307,6 +1307,13 @@ MINI_OP(OP_GC_SAFE_POINT, "gc_safe_point", NONE, IREG, NONE)
  */
 MINI_OP(OP_GENERIC_CLASS_INIT, "generic_class_init", NONE, IREG, NONE)
 
+/*
+ * Call mini_init_method_rgctx () if needed.
+ * sreg1 is a MonoMethodRuntimeGenericContext.
+ * sreg2 is a MonoGSharedMethodInfo.
+ */
+MINI_OP(OP_INIT_MRGCTX, "init_mrgctx", NONE, IREG, IREG)
+
 /* Arch specific opcodes */
 #if defined(TARGET_X86) || defined(TARGET_AMD64)
 MINI_OP(OP_X86_TEST_NULL,          "x86_test_null", NONE, IREG, NONE)
index f025de7f5ba5989bc9ee8c954f4b321b30dbe1fe..7f4a675bdbc046f1778100d7b1a8a7f417dac6fc 100644 (file)
@@ -3018,6 +3018,9 @@ init_backend (MonoBackend *backend)
 #ifdef MONO_ARCH_FORCE_FLOAT32
        backend->force_float32 = 1;
 #endif
+#ifdef MONO_ARCH_HAVE_INIT_MRGCTX
+       backend->have_init_mrgctx = 1;
+#endif
 }
 
 static gboolean
index 943242eadb4940b4517bc5d2b7225c7019b33276..b70d344340ec99b4e4becf75ad465f61ee3c05c1 100644 (file)
@@ -1246,6 +1246,7 @@ typedef struct {
        gboolean         have_op_tailcall_membase : 1;
        gboolean         have_op_tailcall_reg : 1;
        gboolean         have_volatile_non_param_register : 1;
+       guint            have_init_mrgctx : 1;
        guint            gshared_supported : 1;
        guint            ilp32 : 1;
        guint            need_got_var : 1;