Skip to content

Commit

Permalink
[mono] Implement LoadPair{,Scalar}Vector{64,128}{,NonTemporal}
Browse files Browse the repository at this point in the history
  • Loading branch information
imhameed committed Jun 26, 2021
1 parent fab6ef3 commit ec909cb
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 0 deletions.
58 changes: 58 additions & 0 deletions src/mono/mono/mini/mini-llvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,21 @@ simd_class_to_llvm_type (EmitContext *ctx, MonoClass *klass)
}
}

static LLVMTypeRef
simd_valuetuple_to_llvm_type (EmitContext *ctx, MonoClass *klass)
{
const char *klass_name = m_class_get_name (klass);
if (!strcmp (klass_name, "ValueTuple`2")) {
MonoType *etype = mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
if (etype->type != MONO_TYPE_GENERICINST)
g_assert_not_reached ();
MonoClass *eklass = etype->data.generic_class->cached_class;
LLVMTypeRef ltype = simd_class_to_llvm_type (ctx, eklass);
return LLVMArrayType (ltype, 2);
}
g_assert_not_reached ();
}

/* Return the 128 bit SIMD type corresponding to the mono type TYPE */
static inline G_GNUC_UNUSED LLVMTypeRef
type_to_sse_type (int type)
Expand Down Expand Up @@ -10452,6 +10467,49 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
values [ins->dreg] = result;
break;
}
case OP_ARM64_LDNP:
case OP_ARM64_LDNP_SCALAR:
case OP_ARM64_LDP:
case OP_ARM64_LDP_SCALAR: {
const char *oname = NULL;
gboolean nontemporal = FALSE;
gboolean scalar = FALSE;
switch (ins->opcode) {
case OP_ARM64_LDNP: oname = "arm64_ldnp"; nontemporal = TRUE; break;
case OP_ARM64_LDNP_SCALAR: oname = "arm64_ldnp_scalar"; nontemporal = TRUE; scalar = TRUE; break;
case OP_ARM64_LDP: oname = "arm64_ldp"; break;
case OP_ARM64_LDP_SCALAR: oname = "arm64_ldp_scalar"; scalar = TRUE; break;
}
if (!addresses [ins->dreg])
addresses [ins->dreg] = build_named_alloca (ctx, m_class_get_byval_arg (ins->klass), oname);
LLVMTypeRef ret_t = simd_valuetuple_to_llvm_type (ctx, ins->klass);
LLVMTypeRef vec_t = LLVMGetElementType (ret_t);
LLVMValueRef ix = const_int32 (1);
LLVMTypeRef src_t = LLVMPointerType (scalar ? LLVMGetElementType (vec_t) : vec_t, 0);
LLVMValueRef src0 = convert (ctx, lhs, src_t);
LLVMValueRef src1 = LLVMBuildGEP (builder, src0, &ix, 1, oname);
LLVMValueRef vals [] = { src0, src1 };
for (int i = 0; i < 2; ++i) {
vals [i] = LLVMBuildLoad (builder, vals [i], oname);
if (nontemporal)
set_nontemporal_flag (vals [i]);
}
unsigned int vec_sz = mono_llvm_get_prim_size_bits (vec_t);
if (scalar) {
g_assert (vec_sz == 64);
LLVMValueRef undef = LLVMGetUndef (vec_t);
for (int i = 0; i < 2; ++i)
vals [i] = LLVMBuildInsertElement (builder, undef, vals [i], const_int32 (0), oname);
}
LLVMValueRef val = LLVMGetUndef (ret_t);
for (int i = 0; i < 2; ++i)
val = LLVMBuildInsertValue (builder, val, vals [i], i, oname);
LLVMTypeRef retptr_t = LLVMPointerType (ret_t, 0);
LLVMValueRef dst = convert (ctx, addresses [ins->dreg], retptr_t);
LLVMBuildStore (builder, val, dst);
values [ins->dreg] = vec_sz == 64 ? val : NULL;
break;
}
case OP_ARM64_ST1: {
LLVMTypeRef t = LLVMTypeOf (rhs);
LLVMValueRef address = convert (ctx, lhs, LLVMPointerType (t, 0));
Expand Down
9 changes: 9 additions & 0 deletions src/mono/mono/mini/mini-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -1604,6 +1604,15 @@ MINI_OP3(OP_ARM64_LD1_INSERT, "arm64_ld1_insert", XREG, IREG, XREG, IREG)
MINI_OP(OP_ARM64_LD1, "arm64_ld1", XREG, IREG, NONE)
MINI_OP(OP_ARM64_LD1R, "arm64_ld1r", XREG, IREG, NONE)

/* Loads two consecutive vector (or scalar) values into a pair of
* vector registers. Returns a ValueTuple in a vreg. klass must be set to the
* MonoClass representing the ValueTuple return type of the op.
*/
MINI_OP(OP_ARM64_LDNP, "arm64_ldnp", VREG, IREG, NONE)
MINI_OP(OP_ARM64_LDNP_SCALAR, "arm64_ldnp_scalar", VREG, IREG, NONE)
MINI_OP(OP_ARM64_LDP, "arm64_ldp", VREG, IREG, NONE)
MINI_OP(OP_ARM64_LDP_SCALAR, "arm64_ldp_scalar", VREG, IREG, NONE)

MINI_OP(OP_ARM64_ST1, "arm64_st1", NONE, IREG, XREG)
MINI_OP(OP_ARM64_SXTL, "arm64_sxtl", XREG, XREG, NONE)
MINI_OP(OP_ARM64_SXTL2, "arm64_sxtl2", XREG, XREG, NONE)
Expand Down
9 changes: 9 additions & 0 deletions src/mono/mono/mini/simd-intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,9 @@ emit_simd_ins (MonoCompile *cfg, MonoClass *klass, int opcode, int sreg1, int sr
} else if (spec [MONO_INST_DEST] == 'f') {
ins->dreg = alloc_freg (cfg);
ins->type = STACK_R8;
} else if (spec [MONO_INST_DEST] == 'v') {
ins->dreg = alloc_dreg (cfg, STACK_VTYPE);
ins->type = STACK_VTYPE;
}
ins->sreg1 = sreg1;
ins->sreg2 = sreg2;
Expand Down Expand Up @@ -1210,6 +1213,12 @@ static SimdIntrinsic advsimd_methods [] = {
{SN_LoadAndInsertScalar, OP_ARM64_LD1_INSERT},
{SN_LoadAndReplicateToVector128, OP_ARM64_LD1R},
{SN_LoadAndReplicateToVector64, OP_ARM64_LD1R},
{SN_LoadPairScalarVector64, OP_ARM64_LDP_SCALAR},
{SN_LoadPairScalarVector64NonTemporal, OP_ARM64_LDNP_SCALAR},
{SN_LoadPairVector128, OP_ARM64_LDP},
{SN_LoadPairVector128NonTemporal, OP_ARM64_LDNP},
{SN_LoadPairVector64, OP_ARM64_LDP},
{SN_LoadPairVector64NonTemporal, OP_ARM64_LDNP},
{SN_LoadVector128, OP_ARM64_LD1},
{SN_LoadVector64, OP_ARM64_LD1},
{SN_Max, OP_XOP_OVR_X_X_X, INTRINS_AARCH64_ADV_SIMD_SMAX, OP_XOP_OVR_X_X_X, INTRINS_AARCH64_ADV_SIMD_UMAX, OP_XOP_OVR_X_X_X, INTRINS_AARCH64_ADV_SIMD_FMAX},
Expand Down
6 changes: 6 additions & 0 deletions src/mono/mono/mini/simd-methods.h
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,12 @@ METHOD(InsertSelectedScalar)
METHOD(LoadAndInsertScalar)
METHOD(LoadAndReplicateToVector128)
METHOD(LoadAndReplicateToVector64)
METHOD(LoadPairScalarVector64)
METHOD(LoadPairScalarVector64NonTemporal)
METHOD(LoadPairVector128)
METHOD(LoadPairVector128NonTemporal)
METHOD(LoadPairVector64)
METHOD(LoadPairVector64NonTemporal)
METHOD(LoadVector64)
METHOD(MaxAcross)
METHOD(MaxNumber)
Expand Down

0 comments on commit ec909cb

Please sign in to comment.