Skip to content

Commit

Permalink
[mono] RuntimeHelpers.CreateSpan<T> is now intrinsic. (#81695)
Browse files Browse the repository at this point in the history
* [mono] RuntimeHelpers.CreateSpan is now intrinsic.

* [mono][jit] RuntimeHelpers.CreateSpan intrinsic fixes.

* [mono][jit] RuntimeHelpers.CreateSpan is intrinsic and seems to work.

* [mono] Fixed a warning that broke build.

* [mono] Pointer arithmetic warnings hopefully solved.

* [mono] Fix pointer conversion warning, take 2.

* [mono] RuntimeHelpers.CreateSpan<T> is no longer intrinsic under AOT.

* [mono] RuntimeHelpers.CreateSpan<T> now constructs the result in a safer way.

* [mono][aot] RuntimeHelpers.CreateSpan<T> intrinsic fixed for AOT case.

* [mono] Cleaned up whitespace changes in decompose.c, YAGNI in ir-emit.h.

* [mono] OP_LDTOKEN_FIELD mini opcode introduced for RuntimeHelpers.CreateSpan<T>

* [mono][aot] RuntimeHelpers.CreateSpan<T> intrinsic now emits the correct AOT constant.

* [mono] RuntimeHelpers.CreateSpan intrinsic, removed superfluous sanity checks.
  • Loading branch information
jandupej authored Feb 13, 2023
1 parent be84df7 commit 7e154e1
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/mono/mono/mini/decompose.c
Original file line number Diff line number Diff line change
Expand Up @@ -1214,6 +1214,10 @@ mono_decompose_vtype_opts (MonoCompile *cfg)
mono_simd_decompose_intrinsic (cfg, bb, ins);
#endif
switch (ins->opcode) {
case OP_LDTOKEN_FIELD:
ins->opcode = OP_VMOVE;
restart = TRUE;
break;
case OP_VMOVE: {
g_assert (ins->klass);
if (COMPILE_LLVM (cfg) && !mini_is_gsharedvt_klass (ins->klass))
Expand Down
43 changes: 43 additions & 0 deletions src/mono/mono/mini/intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -1010,6 +1010,49 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
EMIT_NEW_UNALU (cfg, ins, OP_ICGT, dreg, -1);
ins->type = STACK_I4;
return ins;
} else if (!strcmp (cmethod->name, "CreateSpan") && fsig->param_count == 1) {
MonoGenericContext* ctx = mono_method_get_context (cmethod);
g_assert (ctx);
g_assert (ctx->method_inst);
g_assert (ctx->method_inst->type_argc == 1);
MonoType* arg_type = ctx->method_inst->type_argv [0];
MonoType* t = mini_get_underlying_type (arg_type);
g_assert (!MONO_TYPE_IS_REFERENCE (t) && t->type != MONO_TYPE_VALUETYPE);

// This OP_LDTOKEN_FIELD later changes into a OP_VMOVE.
MonoClassField* field = (MonoClassField*) args [0]->inst_p1;
if (args [0]->opcode != OP_LDTOKEN_FIELD)
return NULL;

int alignment = 0;
const int element_size = mono_type_size (t, &alignment);
const int num_elements = mono_type_size (field->type, &alignment) / element_size;
const int obj_size = MONO_ABI_SIZEOF (MonoObject);

MonoInst* span = mono_compile_create_var (cfg, fsig->ret, OP_LOCAL);
MonoInst* span_addr;
EMIT_NEW_TEMPLOADA (cfg, span_addr, span->inst_c0);

MonoInst* ptr_inst;
if (cfg->compile_aot) {
NEW_RVACONST (cfg, ptr_inst, mono_class_get_image (mono_field_get_parent (field)), args [0]->inst_c0);
MONO_ADD_INS (cfg->cbb, ptr_inst);
} else {
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
const int swizzle = 1;
#else
const int swizzle = element_size;
#endif
gpointer data_ptr = (gpointer)mono_field_get_rva (field, swizzle);
EMIT_NEW_PCONST (cfg, ptr_inst, data_ptr);
}

MonoClassField* field_ref = mono_class_get_field_from_name_full (span->klass, "_reference", NULL);
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, span_addr->dreg, field_ref->offset - obj_size, ptr_inst->dreg);
MonoClassField* field_len = mono_class_get_field_from_name_full (span->klass, "_length", NULL);
MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STOREI4_MEMBASE_IMM, span_addr->dreg, field_len->offset - obj_size, num_elements);
EMIT_NEW_TEMPLOAD (cfg, ins, span->inst_c0);
return ins;
} else
return NULL;
} else if (cmethod->klass == mono_class_try_get_memory_marshal_class ()) {
Expand Down
2 changes: 2 additions & 0 deletions src/mono/mono/mini/ir-emit.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,8 @@ alloc_dreg (MonoCompile *cfg, MonoStackType stack_type)

#define NEW_LDSTRCONST(cfg,dest,image,token) NEW_AOTCONST_TOKEN ((cfg), (dest), MONO_PATCH_INFO_LDSTR, (image), (token), NULL, STACK_OBJ, mono_defaults.string_class)

#define NEW_RVACONST(cfg,dest,image,token) NEW_AOTCONST_TOKEN ((cfg), (dest), MONO_PATCH_INFO_RVA, (image), (token), NULL, STACK_MP, NULL)

#define NEW_LDSTRLITCONST(cfg,dest,val) NEW_AOTCONST ((cfg), (dest), MONO_PATCH_INFO_LDSTR_LIT, (val))

#define NEW_TYPE_FROM_HANDLE_CONST(cfg,dest,image,token,generic_context) NEW_AOTCONST_TOKEN ((cfg), (dest), MONO_PATCH_INFO_TYPE_FROM_HANDLE, (image), (token), (generic_context), STACK_OBJ, mono_defaults.runtimetype_class)
Expand Down
7 changes: 7 additions & 0 deletions src/mono/mono/mini/method-to-ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -10901,9 +10901,16 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
} else {
EMIT_NEW_PCONST (cfg, ins, handle);
}

EMIT_NEW_TEMPLOADA (cfg, addr, vtvar->inst_c0);
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, addr->dreg, 0, ins->dreg);
EMIT_NEW_TEMPLOAD (cfg, ins, vtvar->inst_c0);
ins->opcode = OP_LDTOKEN_FIELD;
ins->inst_c0 = n;
ins->inst_p1 = handle;

cfg->flags |= MONO_CFG_NEEDS_DECOMPOSE;
cfg->cbb->needs_decompose = TRUE;
}
}

Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/mini/mini-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,7 @@ MINI_OP(OP_LOAD_GOTADDR, "load_gotaddr", IREG, NONE, NONE)
MINI_OP(OP_DUMMY_USE, "dummy_use", NONE, IREG, NONE)
MINI_OP(OP_NOT_REACHED, "not_reached", NONE, NONE, NONE)
MINI_OP(OP_NOT_NULL, "not_null", NONE, IREG, NONE)
MINI_OP(OP_LDTOKEN_FIELD, "ldtoken_field", VREG, VREG, NONE)

/* SIMD opcodes. */

Expand Down

0 comments on commit 7e154e1

Please sign in to comment.