Skip to content

Commit

Permalink
Add mono support.
Browse files Browse the repository at this point in the history
  • Loading branch information
vargaz committed Mar 31, 2023
1 parent 6d9e136 commit f247b3c
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 7 deletions.
6 changes: 6 additions & 0 deletions src/mono/mono/mini/llvm-intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,12 @@ INTRINS_OVR_TAG(AARCH64_ADV_SIMD_SRI, aarch64_neon_vsri, Arm64, V64 | V128 | I1

INTRINS_OVR_TAG(AARCH64_ADV_SIMD_TBX1, aarch64_neon_tbx1, Arm64, V64 | V128 | I1)
INTRINS_OVR_TAG(AARCH64_ADV_SIMD_TBL1, aarch64_neon_tbl1, Arm64, V64 | V128 | I1)
INTRINS_OVR_TAG(AARCH64_ADV_SIMD_TBX2, aarch64_neon_tbx2, Arm64, V64 | V128 | I1)
INTRINS_OVR_TAG(AARCH64_ADV_SIMD_TBL2, aarch64_neon_tbl2, Arm64, V64 | V128 | I1)
INTRINS_OVR_TAG(AARCH64_ADV_SIMD_TBX3, aarch64_neon_tbx3, Arm64, V64 | V128 | I1)
INTRINS_OVR_TAG(AARCH64_ADV_SIMD_TBL3, aarch64_neon_tbl3, Arm64, V64 | V128 | I1)
INTRINS_OVR_TAG(AARCH64_ADV_SIMD_TBX4, aarch64_neon_tbx4, Arm64, V64 | V128 | I1)
INTRINS_OVR_TAG(AARCH64_ADV_SIMD_TBL4, aarch64_neon_tbl4, Arm64, V64 | V128 | I1)

INTRINS_OVR_TAG_KIND(AARCH64_ADV_SIMD_SDOT, aarch64_neon_sdot, Arm64, Arm64DotProd, V64 | V128 | I4)
INTRINS_OVR_TAG_KIND(AARCH64_ADV_SIMD_UDOT, aarch64_neon_udot, Arm64, Arm64DotProd, V64 | V128 | I4)
Expand Down
57 changes: 57 additions & 0 deletions src/mono/mono/mini/mini-llvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -11312,6 +11312,63 @@ MONO_RESTORE_WARNING
values [ins->dreg] = result;
break;
}
case OP_ARM64_TBL_INDIRECT:
case OP_ARM64_TBX_INDIRECT: {
int nvectors = ins->inst_c0;
guint32 *offsets = (guint32*)ins->inst_p1;

LLVMValueRef args [16];

LLVMTypeRef etype = LLVMVectorType (LLVMInt8Type (), 16);

int aindex = 0;

LLVMValueRef table_val, default_values_val, indexes_val;
if (ins->opcode == OP_ARM64_TBX_INDIRECT) {
table_val = lhs;
default_values_val = rhs;
indexes_val = arg3;
args [aindex ++] = default_values_val;
} else {
table_val = lhs;
indexes_val = rhs;
}

/* Load input vectors from memory */
LLVMValueRef addr = convert (ctx, table_val, pointer_type (etype));
for (int i = 0; i < nvectors; ++i) {
g_assert (offsets [i] % 16 == 0);
LLVMValueRef index = const_int32 (offsets [i] / 16);
LLVMValueRef ptr = LLVMBuildGEP2 (builder, etype, addr, &index, 1, "");
args [aindex ++] = emit_load (builder, etype, ptr, "", FALSE);
}
args [aindex ++] = indexes_val;
g_assert (aindex < 16);

IntrinsicId iid = (IntrinsicId)0;
if (ins->opcode == OP_ARM64_TBL_INDIRECT) {
switch (nvectors) {
case 2: iid = INTRINS_AARCH64_ADV_SIMD_TBL2; break;
case 3: iid = INTRINS_AARCH64_ADV_SIMD_TBL3; break;
case 4: iid = INTRINS_AARCH64_ADV_SIMD_TBL4; break;
default:
g_assert_not_reached ();
break;
}
} else {
switch (nvectors) {
case 2: iid = INTRINS_AARCH64_ADV_SIMD_TBX2; break;
case 3: iid = INTRINS_AARCH64_ADV_SIMD_TBX3; break;
case 4: iid = INTRINS_AARCH64_ADV_SIMD_TBX4; break;
default:
g_assert_not_reached ();
break;
}
}
llvm_ovr_tag_t ovr_tag = (LLVMGetVectorSize (LLVMTypeOf (indexes_val)) == 8 ? INTRIN_vector64 : INTRIN_vector128) | INTRIN_int8;
values [ins->dreg] = call_overloaded_intrins (ctx, iid, ovr_tag, args, "");
break;
}
case OP_XOP_OVR_X_X: {
IntrinsicId iid = (IntrinsicId) ins->inst_c0;
llvm_ovr_tag_t ovr_tag = ovr_tag_from_mono_vector_class (ins->klass);
Expand Down
8 changes: 8 additions & 0 deletions src/mono/mono/mini/mini-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -1755,6 +1755,14 @@ MINI_OP3(OP_ARM64_SQRDMLSH, "arm64_sqrdmlsh", XREG, XREG, XREG, XREG)
MINI_OP3(OP_ARM64_SQRDMLSH_BYSCALAR, "arm64_sqrdmlsh_byscalar", XREG, XREG, XREG, XREG)
MINI_OP3(OP_ARM64_SQRDMLSH_SCALAR, "arm64_sqrdmlsh_scalar", XREG, XREG, XREG, XREG)

/*
* sreg1 points to a memory area with the input vectors.
* inst_c0 is the number of vectors.
* inst_p1 points to an int array with the offsets inside the memory area.
*/
MINI_OP(OP_ARM64_TBL_INDIRECT, "arm64_tbl_indirect", XREG, IREG, XREG)
MINI_OP3(OP_ARM64_TBX_INDIRECT, "arm64_tbx_indirect", XREG, IREG, XREG, XREG)

#endif // TARGET_ARM64

MINI_OP(OP_FCVTL, "convert_to_higher_precision", XREG, XREG, NONE)
Expand Down
63 changes: 56 additions & 7 deletions src/mono/mono/mini/simd-intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -3562,13 +3562,62 @@ emit_arm64_intrinsics (
return ret;
}
case SN_VectorTableLookup:
if (!type_is_simd_vector (fsig->params [0]) || !type_is_simd_vector (fsig->params [1]))
return NULL;
return emit_simd_ins_for_sig (cfg, klass, OP_XOP_OVR_X_X_X, INTRINS_AARCH64_ADV_SIMD_TBL1, 0, fsig, args);
case SN_VectorTableLookupExtension:
if (!type_is_simd_vector (fsig->params [0]) || !type_is_simd_vector (fsig->params [1]))
return NULL;
return emit_simd_ins_for_sig (cfg, klass, OP_XOP_OVR_X_X_X_X, INTRINS_AARCH64_ADV_SIMD_TBX1, 0, fsig, args);
case SN_VectorTableLookupExtension: {
if (type_is_simd_vector (fsig->params [0]) && type_is_simd_vector (fsig->params [1])) {
if (id == SN_VectorTableLookup)
return emit_simd_ins_for_sig (cfg, klass, OP_XOP_OVR_X_X_X, INTRINS_AARCH64_ADV_SIMD_TBL1, 0, fsig, args);
else
return emit_simd_ins_for_sig (cfg, klass, OP_XOP_OVR_X_X_X_X, INTRINS_AARCH64_ADV_SIMD_TBX1, 0, fsig, args);
}

MonoInst *ins, *addr;
int tuple_argindex;

if (id == SN_VectorTableLookup)
/* VectorTableLookup((Vector128<sbyte>, Vector128<sbyte>) table, Vector128<sbyte> byteIndexes) */
tuple_argindex = 0;
else
/* VectorTableLookupExtension(Vector128<byte> defaultValues, (Vector128<byte>, Vector128<byte>) table, Vector128<byte> byteIndexes */
tuple_argindex = 1;

/*
* These intrinsics have up to 5 inputs, and our IR can't model that, so save the inputs to the stack and have
* the LLVM implementation read them back.
*/
MonoType *tuple_type = fsig->params [tuple_argindex];
g_assert (tuple_type->type == MONO_TYPE_GENERICINST);
MonoClass *tclass = mono_class_from_mono_type_internal (tuple_type);
mono_class_init_internal (tclass);

MonoClassField *fields = m_class_get_fields (tclass);
int nfields = mono_class_get_field_count (tclass);
guint32 *offsets = mono_mempool_alloc0 (cfg->mempool, nfields * sizeof (guint32));
for (int i = 0; i < mono_class_get_field_count (tclass); ++i)
offsets [i] = mono_field_get_offset (&fields [i]) - MONO_ABI_SIZEOF (MonoObject);

int vreg = alloc_xreg (cfg);
NEW_VARLOADA_VREG (cfg, addr, vreg, tuple_type);
MONO_ADD_INS (cfg->cbb, addr);

EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, tuple_type, addr->dreg, 0, args [tuple_argindex]->dreg);

MONO_INST_NEW (cfg, ins, id == SN_VectorTableLookup ? OP_ARM64_TBL_INDIRECT : OP_ARM64_TBX_INDIRECT);
ins->dreg = alloc_xreg (cfg);
ins->sreg1 = addr->dreg;
if (id == SN_VectorTableLookup) {
/* byteIndexes */
ins->sreg2 = args [1]->dreg;
} else {
/* defaultValues */
ins->sreg2 = args [0]->dreg;
/* byteIndexes */
ins->sreg3 = args [2]->dreg;
}
ins->inst_c0 = nfields;
ins->inst_p1 = offsets;
MONO_ADD_INS (cfg->cbb, ins);
return ins;
}
default:
g_assert_not_reached ();
}
Expand Down

0 comments on commit f247b3c

Please sign in to comment.