Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mono][jit] Enabled Ctor, Set_Item and Get_Item Vector4 intrinsics for miniJIT on ARM64 #89501

Merged
merged 2 commits into from
Jul 28, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 84 additions & 26 deletions src/mono/mono/mini/simd-intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -2592,21 +2592,10 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
return NULL;
}

if (!COMPILE_LLVM (cfg)) {
#ifndef TARGET_ARM64
if (!COMPILE_LLVM (cfg))
return NULL;
#else
// when a method gets enabled should be removed from here
switch (id) {
case SN_ctor:
case SN_get_Item:
case SN_set_Item:
return NULL;
default:
break;
}
#endif
}

if (cfg->verbose_level > 1) {
char *name = mono_method_full_name (cmethod, TRUE);
Expand All @@ -2628,10 +2617,13 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f

int opcode = type_to_expand_op (etype->type);
ins = emit_simd_ins (cfg, klass, opcode, args [1]->dreg, -1);
ins->dreg = dreg;
ins->inst_c1 = MONO_TYPE_R4;

for (int i = 1; i < fsig->param_count; ++i) {
ins = emit_simd_ins (cfg, klass, OP_INSERT_R4, ins->dreg, args [i + 1]->dreg);
ins->inst_c0 = i;
ins->inst_c1 = MONO_TYPE_R4;
}
ins->dreg = dreg;

Expand Down Expand Up @@ -2675,13 +2667,44 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
break;
case SN_get_Item: {
// GetElement is marked as Intrinsic, but handling this in get_Item leads to better code
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [1]->dreg, len);
MONO_EMIT_NEW_COND_EXC (cfg, GE_UN, "ArgumentOutOfRangeException");
MonoTypeEnum ty = etype->type;
int opcode = type_to_xextract_op (ty);
int src1 = load_simd_vreg (cfg, cmethod, args [0], NULL);
ins = emit_simd_ins (cfg, klass, opcode, src1, args [1]->dreg);
ins->inst_c1 = ty;
int elems = 4;
MonoTypeEnum ty = etype->type;

if (args [1]->opcode == OP_ICONST) {
// If the index is provably a constant, we can generate vastly better code.
int index = args[1]->inst_c0;

if (index < 0 || index >= elems) {
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [1]->dreg, elems);
MONO_EMIT_NEW_COND_EXC (cfg, GE_UN, "ArgumentOutOfRangeException");
}

int opcode = type_to_extract_op (ty);
ins = emit_simd_ins (cfg, klass, opcode, src1, -1);
ins->inst_c0 = args[1]->inst_c0;
ins->inst_c1 = ty;
return ins;
}

MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [1]->dreg, elems);
MONO_EMIT_NEW_COND_EXC (cfg, GE_UN, "ArgumentOutOfRangeException");

if (COMPILE_LLVM (cfg)) {
int opcode = type_to_xextract_op (ty);
ins = emit_simd_ins (cfg, klass, opcode, src1, args [1]->dreg);
ins->inst_c1 = ty;
} else {
// Load back from vector_dreg + index << elem_size_log2
// TODO: on x86, use a LEA
int offset_reg = alloc_freg (cfg);
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHL_IMM, offset_reg, args [1]->dreg, type_to_width_log2 (ty));
int addr_reg = alloc_freg (cfg);
MONO_EMIT_NEW_BIALU(cfg, OP_PADD, addr_reg, args [0]->dreg, offset_reg);
int dreg = alloc_freg (cfg);
NEW_LOAD_MEMBASE (cfg, ins, mono_type_to_load_membase (cfg, fsig->ret), dreg, addr_reg, 0);
MONO_ADD_INS (cfg->cbb, ins);
}
return ins;
}
case SN_get_Zero:
Expand Down Expand Up @@ -2732,17 +2755,52 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
g_assert (fsig->hasthis && fsig->param_count == 2 && fsig->params [0]->type == MONO_TYPE_I4 && fsig->params [1]->type == MONO_TYPE_R4);

gboolean indirect = FALSE;
int elems = 4, index = args [1]->inst_c0;
int dreg = load_simd_vreg (cfg, cmethod, args [0], &indirect);

MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [1]->dreg, len);
if (args [1]->opcode == OP_ICONST) {
// If the index is provably a constant, we can generate vastly better code.
// Bounds check only if the index is out of range
if (index < 0 || index >= elems) {
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [1]->dreg, elems);
MONO_EMIT_NEW_COND_EXC (cfg, GE_UN, "ArgumentOutOfRangeException");
}

ins = emit_simd_ins (cfg, klass, OP_INSERT_R4, dreg, args [2]->dreg);
ins->inst_c0 = index;
ins->inst_c1 = MONO_TYPE_R4;
ins->dreg = dreg;

if (indirect) {
EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STOREX_MEMBASE, args [0]->dreg, 0, dreg);
ins->klass = klass;
}

return ins;
}

MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [1]->dreg, elems);
MONO_EMIT_NEW_COND_EXC (cfg, GE_UN, "ArgumentOutOfRangeException");
ins = emit_simd_ins (cfg, klass, OP_XINSERT_R4, dreg, args [2]->dreg);
ins->sreg3 = args [1]->dreg;
ins->inst_c1 = MONO_TYPE_R4;
ins->dreg = dreg;
if (indirect) {
EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STOREX_MEMBASE, args [0]->dreg, 0, dreg);
ins->klass = klass;

if (COMPILE_LLVM (cfg)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that there is something that we could do to simplify this code path. Please open an issue to track it. You could say something like "Merge LLVM and non-llvm code path in emit_vector_2_3_4" in the issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ins = emit_simd_ins (cfg, klass, OP_XINSERT_R4, dreg, args [2]->dreg);
ins->sreg3 = args [1]->dreg;
ins->inst_c1 = MONO_TYPE_R4;
ins->dreg = dreg;

if (indirect) {
EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STOREX_MEMBASE, args [0]->dreg, 0, dreg);
ins->klass = klass;
}
} else {
// Overwrite [vector_dreg + index << elem_size_log2] with replacement value
// TODO: on x86, use a LEA
int offset_reg = alloc_freg (cfg);
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHL_IMM, offset_reg, args [1]->dreg, type_to_width_log2 (MONO_TYPE_R4));
int addr_reg = alloc_freg (cfg);
MONO_EMIT_NEW_BIALU(cfg, OP_PADD, addr_reg, args [0]->dreg, offset_reg);

EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, fsig->params [1], addr_reg, 0, args [2]->dreg);
}

return ins;
Expand Down