mirror of
https://github.com/VSadov/Satori.git
synced 2025-06-10 18:11:04 +09:00
Add VectorTableList and TableVectorExtension intrinsics (#35600)
This commit is contained in:
parent
0764d8c117
commit
aa81328f4e
25 changed files with 4776 additions and 20 deletions
|
@ -1222,9 +1222,11 @@ protected:
|
|||
|
||||
#define PERFSCORE_THROUGHPUT_ILLEGAL -1024.0f
|
||||
|
||||
#define PERFSCORE_THROUGHPUT_4X 0.25f // Fastest - Quad issue
|
||||
#define PERFSCORE_THROUGHPUT_3X (1.0f / 3.0f) // Faster - Three issue
|
||||
#define PERFSCORE_THROUGHPUT_2X 0.5f // Faster - Dual issue
|
||||
#define PERFSCORE_THROUGHPUT_6X (1.0f / 6.0f) // Hextuple issue
|
||||
#define PERFSCORE_THROUGHPUT_5X 0.20f // Pentuple issue
|
||||
#define PERFSCORE_THROUGHPUT_4X 0.25f // Quad issue
|
||||
#define PERFSCORE_THROUGHPUT_3X (1.0f / 3.0f) // Three issue
|
||||
#define PERFSCORE_THROUGHPUT_2X 0.5f // Dual issue
|
||||
|
||||
#define PERFSCORE_THROUGHPUT_1C 1.0f // Single Issue
|
||||
|
||||
|
|
|
@ -817,6 +817,22 @@ void emitter::emitInsSanityCheck(instrDesc* id)
|
|||
break;
|
||||
|
||||
case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
|
||||
switch (id->idIns())
|
||||
{
|
||||
case INS_tbl:
|
||||
case INS_tbl_2regs:
|
||||
case INS_tbl_3regs:
|
||||
case INS_tbl_4regs:
|
||||
case INS_tbx:
|
||||
case INS_tbx_2regs:
|
||||
case INS_tbx_3regs:
|
||||
case INS_tbx_4regs:
|
||||
elemsize = optGetElemsize(id->idInsOpt());
|
||||
assert(elemsize == EA_1BYTE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
assert(isValidVectorDatasize(id->idOpSize()));
|
||||
assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
|
||||
assert(isVectorRegister(id->idReg1()));
|
||||
|
@ -3213,15 +3229,16 @@ emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
|
|||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// insGetLoadStoreRegisterListSize: Returns a size of the register list a given instruction operates on.
|
||||
// insGetRegisterListSize: Returns a size of the register list a given instruction operates on.
|
||||
//
|
||||
// Arguments:
|
||||
// ins - A Load/Store Vector instruction (e.g. ld1 (2 registers), ld1r, st1).
|
||||
// ins - An instruction which uses a register list
|
||||
// (e.g. ld1 (2 registers), ld1r, st1, tbl, tbx).
|
||||
//
|
||||
// Return value:
|
||||
// A number of consecutive SIMD and floating-point registers the instruction loads to/store from.
|
||||
//
|
||||
/*static*/ unsigned emitter::insGetLoadStoreRegisterListSize(instruction ins)
|
||||
/*static*/ unsigned emitter::insGetRegisterListSize(instruction ins)
|
||||
{
|
||||
unsigned registerListSize = 0;
|
||||
|
||||
|
@ -3230,6 +3247,8 @@ emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
|
|||
case INS_ld1:
|
||||
case INS_ld1r:
|
||||
case INS_st1:
|
||||
case INS_tbl:
|
||||
case INS_tbx:
|
||||
registerListSize = 1;
|
||||
break;
|
||||
|
||||
|
@ -3238,6 +3257,8 @@ emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
|
|||
case INS_ld2r:
|
||||
case INS_st1_2regs:
|
||||
case INS_st2:
|
||||
case INS_tbl_2regs:
|
||||
case INS_tbx_2regs:
|
||||
registerListSize = 2;
|
||||
break;
|
||||
|
||||
|
@ -3246,6 +3267,8 @@ emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
|
|||
case INS_ld3r:
|
||||
case INS_st1_3regs:
|
||||
case INS_st3:
|
||||
case INS_tbl_3regs:
|
||||
case INS_tbx_3regs:
|
||||
registerListSize = 3;
|
||||
break;
|
||||
|
||||
|
@ -3254,6 +3277,8 @@ emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
|
|||
case INS_ld4r:
|
||||
case INS_st1_4regs:
|
||||
case INS_st4:
|
||||
case INS_tbl_4regs:
|
||||
case INS_tbx_4regs:
|
||||
registerListSize = 4;
|
||||
break;
|
||||
|
||||
|
@ -5192,7 +5217,7 @@ void emitter::emitIns_R_R_I(
|
|||
|
||||
if (insOptsAnyArrangement(opt))
|
||||
{
|
||||
registerListSize = insGetLoadStoreRegisterListSize(ins);
|
||||
registerListSize = insGetRegisterListSize(ins);
|
||||
assert(isValidVectorDatasize(size));
|
||||
assert(isValidArrangement(size, opt));
|
||||
assert((size * registerListSize) == imm);
|
||||
|
@ -5226,7 +5251,7 @@ void emitter::emitIns_R_R_I(
|
|||
assert(isValidArrangement(size, opt));
|
||||
|
||||
elemsize = optGetElemsize(opt);
|
||||
registerListSize = insGetLoadStoreRegisterListSize(ins);
|
||||
registerListSize = insGetRegisterListSize(ins);
|
||||
assert((elemsize * registerListSize) == imm);
|
||||
|
||||
// Load single structure and replicate post-indexed by an immediate
|
||||
|
@ -5676,6 +5701,14 @@ void emitter::emitIns_R_R_R(
|
|||
case INS_eor:
|
||||
case INS_orr:
|
||||
case INS_orn:
|
||||
case INS_tbl:
|
||||
case INS_tbl_2regs:
|
||||
case INS_tbl_3regs:
|
||||
case INS_tbl_4regs:
|
||||
case INS_tbx:
|
||||
case INS_tbx_2regs:
|
||||
case INS_tbx_3regs:
|
||||
case INS_tbx_4regs:
|
||||
if (isVectorRegister(reg1))
|
||||
{
|
||||
assert(isValidVectorDatasize(size));
|
||||
|
@ -6612,7 +6645,7 @@ void emitter::emitIns_R_R_I_I(
|
|||
assert(isValidVectorElemsize(elemsize));
|
||||
assert(isValidVectorIndex(EA_16BYTE, elemsize, imm1));
|
||||
|
||||
registerListSize = insGetLoadStoreRegisterListSize(ins);
|
||||
registerListSize = insGetRegisterListSize(ins);
|
||||
assert((elemsize * registerListSize) == (unsigned)imm2);
|
||||
assert(insOptsPostIndex(opt));
|
||||
|
||||
|
@ -11884,7 +11917,7 @@ void emitter::emitDispIns(
|
|||
|
||||
case IF_LS_2D: // LS_2D .Q.............. ....ssnnnnnttttt Vt Rn
|
||||
case IF_LS_2E: // LS_2E .Q.............. ....ssnnnnnttttt Vt Rn
|
||||
registerListSize = insGetLoadStoreRegisterListSize(id->idIns());
|
||||
registerListSize = insGetRegisterListSize(id->idIns());
|
||||
emitDispVectorRegList(id->idReg1(), registerListSize, id->idInsOpt(), true);
|
||||
|
||||
if (fmt == IF_LS_2D)
|
||||
|
@ -11903,7 +11936,7 @@ void emitter::emitDispIns(
|
|||
|
||||
case IF_LS_2F: // LS_2F .Q.............. xx.Sssnnnnnttttt Vt[] Rn
|
||||
case IF_LS_2G: // LS_2G .Q.............. xx.Sssnnnnnttttt Vt[] Rn
|
||||
registerListSize = insGetLoadStoreRegisterListSize(id->idIns());
|
||||
registerListSize = insGetRegisterListSize(id->idIns());
|
||||
elemsize = id->idOpSize();
|
||||
emitDispVectorElemList(id->idReg1(), registerListSize, elemsize, id->idSmallCns(), true);
|
||||
|
||||
|
@ -11967,7 +12000,7 @@ void emitter::emitDispIns(
|
|||
|
||||
case IF_LS_3F: // LS_3F .Q.........mmmmm ....ssnnnnnttttt Vt Rn Rm
|
||||
case IF_LS_3G: // LS_3G .Q.........mmmmm ...Sssnnnnnttttt Vt[] Rn Rm
|
||||
registerListSize = insGetLoadStoreRegisterListSize(id->idIns());
|
||||
registerListSize = insGetRegisterListSize(id->idIns());
|
||||
|
||||
if (fmt == IF_LS_3F)
|
||||
{
|
||||
|
@ -12468,9 +12501,25 @@ void emitter::emitDispIns(
|
|||
|
||||
case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
|
||||
emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
|
||||
if (ins != INS_mov)
|
||||
switch (ins)
|
||||
{
|
||||
emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
|
||||
case INS_tbl:
|
||||
case INS_tbl_2regs:
|
||||
case INS_tbl_3regs:
|
||||
case INS_tbl_4regs:
|
||||
case INS_tbx:
|
||||
case INS_tbx_2regs:
|
||||
case INS_tbx_3regs:
|
||||
case INS_tbx_4regs:
|
||||
registerListSize = insGetRegisterListSize(ins);
|
||||
elemsize = id->idOpSize();
|
||||
emitDispVectorRegList(id->idReg2(), registerListSize, id->idInsOpt(), true);
|
||||
break;
|
||||
case INS_mov:
|
||||
break;
|
||||
default:
|
||||
emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
|
||||
break;
|
||||
}
|
||||
emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
|
||||
break;
|
||||
|
@ -14145,9 +14194,48 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins
|
|||
}
|
||||
break;
|
||||
|
||||
case IF_DV_3C: // mov,and, bic, eor, mov,mvn, orn, bsl, bit, bif (vector)
|
||||
result.insThroughput = PERFSCORE_THROUGHPUT_2X;
|
||||
result.insLatency = PERFSCORE_LATENCY_1C;
|
||||
case IF_DV_3C: // mov,and, bic, eor, mov,mvn, orn, bsl, bit, bif,
|
||||
// tbl, tbx (vector)
|
||||
switch (ins)
|
||||
{
|
||||
case INS_tbl:
|
||||
result.insThroughput = PERFSCORE_THROUGHPUT_2X;
|
||||
result.insLatency = PERFSCORE_LATENCY_1C;
|
||||
break;
|
||||
case INS_tbl_2regs:
|
||||
result.insThroughput = PERFSCORE_THROUGHPUT_3X;
|
||||
result.insLatency = PERFSCORE_LATENCY_2C;
|
||||
break;
|
||||
case INS_tbl_3regs:
|
||||
result.insThroughput = PERFSCORE_THROUGHPUT_4X;
|
||||
result.insLatency = PERFSCORE_LATENCY_3C;
|
||||
break;
|
||||
case INS_tbl_4regs:
|
||||
result.insThroughput = PERFSCORE_THROUGHPUT_3X;
|
||||
result.insLatency = PERFSCORE_LATENCY_4C;
|
||||
break;
|
||||
case INS_tbx:
|
||||
result.insThroughput = PERFSCORE_THROUGHPUT_3X;
|
||||
result.insLatency = PERFSCORE_LATENCY_2C;
|
||||
break;
|
||||
case INS_tbx_2regs:
|
||||
result.insThroughput = PERFSCORE_THROUGHPUT_4X;
|
||||
result.insLatency = PERFSCORE_LATENCY_3C;
|
||||
break;
|
||||
case INS_tbx_3regs:
|
||||
result.insThroughput = PERFSCORE_THROUGHPUT_5X;
|
||||
result.insLatency = PERFSCORE_LATENCY_4C;
|
||||
break;
|
||||
case INS_tbx_4regs:
|
||||
result.insThroughput = PERFSCORE_THROUGHPUT_6X;
|
||||
result.insLatency = PERFSCORE_LATENCY_5C;
|
||||
break;
|
||||
default:
|
||||
// All other instructions
|
||||
result.insThroughput = PERFSCORE_THROUGHPUT_2X;
|
||||
result.insLatency = PERFSCORE_LATENCY_1C;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case IF_DV_2E: // mov, dup (scalar)
|
||||
|
|
|
@ -453,9 +453,9 @@ static emitAttr optGetSrcsize(insOpts conversion);
|
|||
// for an element of size 'elemsize' in a vector register of size 'datasize'
|
||||
static bool isValidVectorIndex(emitAttr datasize, emitAttr elemsize, ssize_t index);
|
||||
|
||||
// For a given Load/Store Vector instruction 'ins' returns a number of consecutive SIMD registers
|
||||
// the instruction loads to/store from.
|
||||
static unsigned insGetLoadStoreRegisterListSize(instruction ins);
|
||||
// For a given instruction 'ins' which contains a register lists returns a
|
||||
// number of consecutive SIMD registers the instruction loads to/store from.
|
||||
static unsigned insGetRegisterListSize(instruction ins);
|
||||
|
||||
/************************************************************************/
|
||||
/* Public inline informational methods */
|
||||
|
|
|
@ -118,6 +118,8 @@ HARDWARE_INTRINSIC(AdvSimd, SqrtScalar,
|
|||
HARDWARE_INTRINSIC(AdvSimd, Store, -1, 2, {INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1}, HW_Category_MemoryStore, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg)
|
||||
HARDWARE_INTRINSIC(AdvSimd, Subtract, -1, 2, {INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_fsub, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
|
||||
HARDWARE_INTRINSIC(AdvSimd, SubtractScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sub, INS_sub, INS_fsub, INS_fsub}, HW_Category_SIMDScalar, HW_Flag_NoFlag)
|
||||
HARDWARE_INTRINSIC(AdvSimd, VectorTableLookup, 8, 2, {INS_tbl, INS_tbl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
|
||||
HARDWARE_INTRINSIC(AdvSimd, VectorTableLookupExtension, 8, 3, {INS_tbx, INS_tbx, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics)
|
||||
HARDWARE_INTRINSIC(AdvSimd, Xor, -1, 2, {INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor}, HW_Category_SimpleSIMD, HW_Flag_Commutative)
|
||||
|
||||
// ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
|
||||
|
@ -195,6 +197,8 @@ HARDWARE_INTRINSIC(AdvSimd_Arm64, TransposeEven, -
|
|||
HARDWARE_INTRINSIC(AdvSimd_Arm64, TransposeOdd, -1, 2, {INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
|
||||
HARDWARE_INTRINSIC(AdvSimd_Arm64, UnzipEven, -1, 2, {INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
|
||||
HARDWARE_INTRINSIC(AdvSimd_Arm64, UnzipOdd, -1, 2, {INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
|
||||
HARDWARE_INTRINSIC(AdvSimd_Arm64, VectorTableLookup, 16, 2, {INS_tbl, INS_tbl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
|
||||
HARDWARE_INTRINSIC(AdvSimd_Arm64, VectorTableLookupExtension, 16, 3, {INS_tbx, INS_tbx, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics)
|
||||
HARDWARE_INTRINSIC(AdvSimd_Arm64, ZipHigh, -1, 2, {INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
|
||||
HARDWARE_INTRINSIC(AdvSimd_Arm64, ZipLow, -1, 2, {INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
|
||||
|
||||
|
|
|
@ -1832,6 +1832,31 @@ INST1(uxtl, "uxtl", 0, 0, IF_DV_2O, 0x2F00A400)
|
|||
|
||||
INST1(uxtl2, "uxtl2", 0, 0, IF_DV_2O, 0x6F00A400)
|
||||
// uxtl2 Vd,Vn DV_2O 011011110iiiiiii 101001nnnnnddddd 6F00 A400 Vd,Vn (shift - vector)
|
||||
|
||||
INST1(tbl, "tbl", 0, 0, IF_DV_3C, 0x0E000000)
|
||||
// tbl Vd,{Vn},Vm DV_3C 0Q001110000mmmmm 000000nnnnnddddd 0E00 0000 Vd,Vn,Vm (vector)
|
||||
|
||||
INST1(tbl_2regs, "tbl", 0, 0, IF_DV_3C, 0x0E002000)
|
||||
// tbl Vd,{Vn,Vn+1},Vm DV_3C 0Q001110000mmmmm 001000nnnnnddddd 0E00 2000 Vd,Vn,Vm (vector)
|
||||
|
||||
INST1(tbl_3regs, "tbl", 0, 0, IF_DV_3C, 0x0E004000)
|
||||
// tbl Vd,{Vn,Vn+1,Vn+2},Vm DV_3C 0Q001110000mmmmm 010000nnnnnddddd 0E00 4000 Vd,Vn,Vm (vector)
|
||||
|
||||
INST1(tbl_4regs, "tbl", 0, 0, IF_DV_3C, 0x0E006000)
|
||||
// tbl Vd,{Vn,Vn+1,Vn+2,Vn+3},Vm DV_3C 0Q001110000mmmmm 011000nnnnnddddd 0E00 6000 Vd,Vn,Vm (vector)
|
||||
|
||||
INST1(tbx, "tbx", 0, 0, IF_DV_3C, 0x0E001000)
|
||||
// tbx Vd,{Vn},Vm DV_3C 0Q001110000mmmmm 000100nnnnnddddd 0E00 1000 Vd,Vn,Vm (vector)
|
||||
|
||||
INST1(tbx_2regs, "tbx", 0, 0, IF_DV_3C, 0x0E003000)
|
||||
// tbx Vd,{Vn,Vn+1},Vm DV_3C 0Q001110000mmmmm 001100nnnnnddddd 0E00 3000 Vd,Vn,Vm (vector)
|
||||
|
||||
INST1(tbx_3regs, "tbx", 0, 0, IF_DV_3C, 0x0E005000)
|
||||
// tbx Vd,{Vn,Vn+1,Vn+2},Vm DV_3C 0Q001110000mmmmm 010100nnnnnddddd 0E00 5000 Vd,Vn,Vm (vector)
|
||||
|
||||
INST1(tbx_4regs, "tbx", 0, 0, IF_DV_3C, 0x0E007000)
|
||||
// tbx Vd,{Vn,Vn+1,Vn+2,Vn+3},Vm DV_3C 0Q001110000mmmmm 011100nnnnnddddd 0E00 7000 Vd,Vn,Vm (vector)
|
||||
|
||||
// clang-format on
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
@ -224,6 +224,10 @@
|
|||
<Compile Include="TransposeOdd.Vector128.UInt16.cs" />
|
||||
<Compile Include="TransposeOdd.Vector128.UInt32.cs" />
|
||||
<Compile Include="TransposeOdd.Vector128.UInt64.cs" />
|
||||
<Compile Include="VectorTableLookup.Vector128.Byte.cs" />
|
||||
<Compile Include="VectorTableLookup.Vector128.SByte.cs" />
|
||||
<Compile Include="VectorTableLookupExtension.Vector128.Byte.cs" />
|
||||
<Compile Include="VectorTableLookupExtension.Vector128.SByte.cs" />
|
||||
<Compile Include="UnzipEven.Vector64.Byte.cs" />
|
||||
<Compile Include="UnzipEven.Vector64.Int16.cs" />
|
||||
<Compile Include="UnzipEven.Vector64.Int32.cs" />
|
||||
|
|
|
@ -224,6 +224,10 @@
|
|||
<Compile Include="TransposeOdd.Vector128.UInt16.cs" />
|
||||
<Compile Include="TransposeOdd.Vector128.UInt32.cs" />
|
||||
<Compile Include="TransposeOdd.Vector128.UInt64.cs" />
|
||||
<Compile Include="VectorTableLookup.Vector128.Byte.cs" />
|
||||
<Compile Include="VectorTableLookup.Vector128.SByte.cs" />
|
||||
<Compile Include="VectorTableLookupExtension.Vector128.Byte.cs" />
|
||||
<Compile Include="VectorTableLookupExtension.Vector128.SByte.cs" />
|
||||
<Compile Include="UnzipEven.Vector64.Byte.cs" />
|
||||
<Compile Include="UnzipEven.Vector64.Int16.cs" />
|
||||
<Compile Include="UnzipEven.Vector64.Int32.cs" />
|
||||
|
|
|
@ -228,6 +228,10 @@ namespace JIT.HardwareIntrinsics.Arm
|
|||
["TransposeOdd.Vector128.UInt16"] = TransposeOdd_Vector128_UInt16,
|
||||
["TransposeOdd.Vector128.UInt32"] = TransposeOdd_Vector128_UInt32,
|
||||
["TransposeOdd.Vector128.UInt64"] = TransposeOdd_Vector128_UInt64,
|
||||
["VectorTableLookup.Vector128.Byte"] = VectorTableLookup_Vector128_Byte,
|
||||
["VectorTableLookup.Vector128.SByte"] = VectorTableLookup_Vector128_SByte,
|
||||
["VectorTableLookupExtension.Vector128.Byte"] = VectorTableLookupExtension_Vector128_Byte,
|
||||
["VectorTableLookupExtension.Vector128.SByte"] = VectorTableLookupExtension_Vector128_SByte,
|
||||
["UnzipEven.Vector64.Byte"] = UnzipEven_Vector64_Byte,
|
||||
["UnzipEven.Vector64.Int16"] = UnzipEven_Vector64_Int16,
|
||||
["UnzipEven.Vector64.Int32"] = UnzipEven_Vector64_Int32,
|
||||
|
|
|
@ -0,0 +1,537 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
/******************************************************************************
|
||||
* This file is auto-generated from a template file by the GenerateTests.csx *
|
||||
* script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make *
|
||||
* changes, please update the corresponding template and run according to the *
|
||||
* directions listed in the file. *
|
||||
******************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.Arm;
|
||||
|
||||
namespace JIT.HardwareIntrinsics.Arm
|
||||
{
|
||||
public static partial class Program
|
||||
{
|
||||
private static void VectorTableLookup_Vector128_Byte()
|
||||
{
|
||||
var test = new SimpleBinaryOpTest__VectorTableLookup_Vector128_Byte();
|
||||
|
||||
if (test.IsSupported)
|
||||
{
|
||||
// Validates basic functionality works, using Unsafe.Read
|
||||
test.RunBasicScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates basic functionality works, using Load
|
||||
test.RunBasicScenario_Load();
|
||||
}
|
||||
|
||||
// Validates calling via reflection works, using Unsafe.Read
|
||||
test.RunReflectionScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates calling via reflection works, using Load
|
||||
test.RunReflectionScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing a static member works
|
||||
test.RunClsVarScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing a static member works, using pinning and Load
|
||||
test.RunClsVarScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing a local works, using Unsafe.Read
|
||||
test.RunLclVarScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing a local works, using Load
|
||||
test.RunLclVarScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing the field of a local class works
|
||||
test.RunClassLclFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing the field of a local class works, using pinning and Load
|
||||
test.RunClassLclFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing an instance member of a class works
|
||||
test.RunClassFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing an instance member of a class works, using pinning and Load
|
||||
test.RunClassFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing the field of a local struct works
|
||||
test.RunStructLclFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing the field of a local struct works, using pinning and Load
|
||||
test.RunStructLclFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing an instance member of a struct works
|
||||
test.RunStructFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing an instance member of a struct works, using pinning and Load
|
||||
test.RunStructFldScenario_Load();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Validates we throw on unsupported hardware
|
||||
test.RunUnsupportedScenario();
|
||||
}
|
||||
|
||||
if (!test.Succeeded)
|
||||
{
|
||||
throw new Exception("One or more scenarios did not complete as expected.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed unsafe class SimpleBinaryOpTest__VectorTableLookup_Vector128_Byte
|
||||
{
|
||||
private struct DataTable
|
||||
{
|
||||
private byte[] inArray1;
|
||||
private byte[] inArray2;
|
||||
private byte[] outArray;
|
||||
|
||||
private GCHandle inHandle1;
|
||||
private GCHandle inHandle2;
|
||||
private GCHandle outHandle;
|
||||
|
||||
private ulong alignment;
|
||||
|
||||
public DataTable(Byte[] inArray1, Byte[] inArray2, Byte[] outArray, int alignment)
|
||||
{
|
||||
int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
|
||||
int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Byte>();
|
||||
int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Byte>();
|
||||
if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
|
||||
{
|
||||
throw new ArgumentException("Invalid value of alignment");
|
||||
}
|
||||
|
||||
this.inArray1 = new byte[alignment * 2];
|
||||
this.inArray2 = new byte[alignment * 2];
|
||||
this.outArray = new byte[alignment * 2];
|
||||
|
||||
this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
|
||||
this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
|
||||
this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
|
||||
|
||||
this.alignment = (ulong)alignment;
|
||||
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Byte, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Byte, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
|
||||
}
|
||||
|
||||
public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
inHandle1.Free();
|
||||
inHandle2.Free();
|
||||
outHandle.Free();
|
||||
}
|
||||
|
||||
private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
|
||||
{
|
||||
return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
|
||||
}
|
||||
}
|
||||
|
||||
private struct TestStruct
|
||||
{
|
||||
public Vector128<Byte> _fld1;
|
||||
public Vector128<Byte> _fld2;
|
||||
|
||||
public static TestStruct Create()
|
||||
{
|
||||
var testStruct = new TestStruct();
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref testStruct._fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (Byte)(TestLibrary.Generator.GetByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
|
||||
return testStruct;
|
||||
}
|
||||
|
||||
public void RunStructFldScenario(SimpleBinaryOpTest__VectorTableLookup_Vector128_Byte testClass)
|
||||
{
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(_fld1, _fld2);
|
||||
|
||||
Unsafe.Write(testClass._dataTable.outArrayPtr, result);
|
||||
testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario_Load(SimpleBinaryOpTest__VectorTableLookup_Vector128_Byte testClass)
|
||||
{
|
||||
fixed (Vector128<Byte>* pFld1 = &_fld1)
|
||||
fixed (Vector128<Byte>* pFld2 = &_fld2)
|
||||
{
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((Byte*)(pFld1)),
|
||||
AdvSimd.LoadVector128((Byte*)(pFld2))
|
||||
);
|
||||
|
||||
Unsafe.Write(testClass._dataTable.outArrayPtr, result);
|
||||
testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly int LargestVectorSize = 16;
|
||||
|
||||
private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
|
||||
private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
|
||||
private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
|
||||
|
||||
private static Byte[] _data1 = new Byte[Op1ElementCount];
|
||||
private static Byte[] _data2 = new Byte[Op2ElementCount];
|
||||
|
||||
private static Vector128<Byte> _clsVar1;
|
||||
private static Vector128<Byte> _clsVar2;
|
||||
|
||||
private Vector128<Byte> _fld1;
|
||||
private Vector128<Byte> _fld2;
|
||||
|
||||
private DataTable _dataTable;
|
||||
|
||||
static SimpleBinaryOpTest__VectorTableLookup_Vector128_Byte()
|
||||
{
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (Byte)(TestLibrary.Generator.GetByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
}
|
||||
|
||||
public SimpleBinaryOpTest__VectorTableLookup_Vector128_Byte()
|
||||
{
|
||||
Succeeded = true;
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (Byte)(TestLibrary.Generator.GetByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (Byte)(TestLibrary.Generator.GetByte() % 20); }
|
||||
_dataTable = new DataTable(_data1, _data2, new Byte[RetElementCount], LargestVectorSize);
|
||||
}
|
||||
|
||||
public bool IsSupported => AdvSimd.Arm64.IsSupported;
|
||||
|
||||
public bool Succeeded { get; set; }
|
||||
|
||||
public void RunBasicScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
|
||||
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(
|
||||
Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
|
||||
Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr)
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunBasicScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
|
||||
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
|
||||
AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunReflectionScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
|
||||
|
||||
var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.VectorTableLookup), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) })
|
||||
.Invoke(null, new object[] {
|
||||
Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
|
||||
Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr)
|
||||
});
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result));
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunReflectionScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
|
||||
|
||||
var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.VectorTableLookup), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) })
|
||||
.Invoke(null, new object[] {
|
||||
AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
|
||||
AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr))
|
||||
});
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result));
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClsVarScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
|
||||
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(
|
||||
_clsVar1,
|
||||
_clsVar2
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClsVarScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
|
||||
|
||||
fixed (Vector128<Byte>* pClsVar1 = &_clsVar1)
|
||||
fixed (Vector128<Byte>* pClsVar2 = &_clsVar2)
|
||||
{
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((Byte*)(pClsVar1)),
|
||||
AdvSimd.LoadVector128((Byte*)(pClsVar2))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunLclVarScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
|
||||
|
||||
var op1 = Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr);
|
||||
var op2 = Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr);
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(op1, op2);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(op1, op2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunLclVarScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
|
||||
|
||||
var op1 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr));
|
||||
var op2 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr));
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(op1, op2);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(op1, op2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassLclFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
|
||||
|
||||
var test = new SimpleBinaryOpTest__VectorTableLookup_Vector128_Byte();
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(test._fld1, test._fld2);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassLclFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
|
||||
|
||||
var test = new SimpleBinaryOpTest__VectorTableLookup_Vector128_Byte();
|
||||
|
||||
fixed (Vector128<Byte>* pFld1 = &test._fld1)
|
||||
fixed (Vector128<Byte>* pFld2 = &test._fld2)
|
||||
{
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((Byte*)(pFld1)),
|
||||
AdvSimd.LoadVector128((Byte*)(pFld2))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunClassFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
|
||||
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(_fld1, _fld2);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
|
||||
|
||||
fixed (Vector128<Byte>* pFld1 = &_fld1)
|
||||
fixed (Vector128<Byte>* pFld2 = &_fld2)
|
||||
{
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((Byte*)(pFld1)),
|
||||
AdvSimd.LoadVector128((Byte*)(pFld2))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunStructLclFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(test._fld1, test._fld2);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructLclFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((Byte*)(&test._fld1)),
|
||||
AdvSimd.LoadVector128((Byte*)(&test._fld2))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
test.RunStructFldScenario(this);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
test.RunStructFldScenario_Load(this);
|
||||
}
|
||||
|
||||
public void RunUnsupportedScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
|
||||
|
||||
bool succeeded = false;
|
||||
|
||||
try
|
||||
{
|
||||
RunBasicScenario_UnsafeRead();
|
||||
}
|
||||
catch (PlatformNotSupportedException)
|
||||
{
|
||||
succeeded = true;
|
||||
}
|
||||
|
||||
if (!succeeded)
|
||||
{
|
||||
Succeeded = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateResult(Vector128<Byte> op1, Vector128<Byte> op2, void* result, [CallerMemberName] string method = "")
|
||||
{
|
||||
Byte[] inArray1 = new Byte[Op1ElementCount];
|
||||
Byte[] inArray2 = new Byte[Op2ElementCount];
|
||||
Byte[] outArray = new Byte[RetElementCount];
|
||||
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), op2);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
|
||||
ValidateResult(inArray1, inArray2, outArray, method);
|
||||
}
|
||||
|
||||
private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
|
||||
{
|
||||
Byte[] inArray1 = new Byte[Op1ElementCount];
|
||||
Byte[] inArray2 = new Byte[Op2ElementCount];
|
||||
Byte[] outArray = new Byte[RetElementCount];
|
||||
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
|
||||
ValidateResult(inArray1, inArray2, outArray, method);
|
||||
}
|
||||
|
||||
private void ValidateResult(Byte[] left, Byte[] right, Byte[] result, [CallerMemberName] string method = "")
|
||||
{
|
||||
bool succeeded = true;
|
||||
|
||||
if (Helpers.TableVectorLookup(0, right, left) != result[0])
|
||||
{
|
||||
succeeded = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 1; i < RetElementCount; i++)
|
||||
{
|
||||
if (Helpers.TableVectorLookup(i, right, left) != result[i])
|
||||
{
|
||||
succeeded = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!succeeded)
|
||||
{
|
||||
TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.VectorTableLookup)}<Byte>(Vector128<Byte>, Vector128<Byte>): {method} failed:");
|
||||
TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
|
||||
TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
|
||||
TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
|
||||
TestLibrary.TestFramework.LogInformation(string.Empty);
|
||||
|
||||
Succeeded = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,537 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
/******************************************************************************
|
||||
* This file is auto-generated from a template file by the GenerateTests.csx *
|
||||
* script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make *
|
||||
* changes, please update the corresponding template and run according to the *
|
||||
* directions listed in the file. *
|
||||
******************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.Arm;
|
||||
|
||||
namespace JIT.HardwareIntrinsics.Arm
|
||||
{
|
||||
public static partial class Program
|
||||
{
|
||||
private static void VectorTableLookup_Vector128_SByte()
|
||||
{
|
||||
var test = new SimpleBinaryOpTest__VectorTableLookup_Vector128_SByte();
|
||||
|
||||
if (test.IsSupported)
|
||||
{
|
||||
// Validates basic functionality works, using Unsafe.Read
|
||||
test.RunBasicScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates basic functionality works, using Load
|
||||
test.RunBasicScenario_Load();
|
||||
}
|
||||
|
||||
// Validates calling via reflection works, using Unsafe.Read
|
||||
test.RunReflectionScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates calling via reflection works, using Load
|
||||
test.RunReflectionScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing a static member works
|
||||
test.RunClsVarScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing a static member works, using pinning and Load
|
||||
test.RunClsVarScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing a local works, using Unsafe.Read
|
||||
test.RunLclVarScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing a local works, using Load
|
||||
test.RunLclVarScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing the field of a local class works
|
||||
test.RunClassLclFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing the field of a local class works, using pinning and Load
|
||||
test.RunClassLclFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing an instance member of a class works
|
||||
test.RunClassFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing an instance member of a class works, using pinning and Load
|
||||
test.RunClassFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing the field of a local struct works
|
||||
test.RunStructLclFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing the field of a local struct works, using pinning and Load
|
||||
test.RunStructLclFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing an instance member of a struct works
|
||||
test.RunStructFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing an instance member of a struct works, using pinning and Load
|
||||
test.RunStructFldScenario_Load();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Validates we throw on unsupported hardware
|
||||
test.RunUnsupportedScenario();
|
||||
}
|
||||
|
||||
if (!test.Succeeded)
|
||||
{
|
||||
throw new Exception("One or more scenarios did not complete as expected.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed unsafe class SimpleBinaryOpTest__VectorTableLookup_Vector128_SByte
|
||||
{
|
||||
private struct DataTable
|
||||
{
|
||||
private byte[] inArray1;
|
||||
private byte[] inArray2;
|
||||
private byte[] outArray;
|
||||
|
||||
private GCHandle inHandle1;
|
||||
private GCHandle inHandle2;
|
||||
private GCHandle outHandle;
|
||||
|
||||
private ulong alignment;
|
||||
|
||||
public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment)
|
||||
{
|
||||
int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
|
||||
int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<SByte>();
|
||||
int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<SByte>();
|
||||
if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
|
||||
{
|
||||
throw new ArgumentException("Invalid value of alignment");
|
||||
}
|
||||
|
||||
this.inArray1 = new byte[alignment * 2];
|
||||
this.inArray2 = new byte[alignment * 2];
|
||||
this.outArray = new byte[alignment * 2];
|
||||
|
||||
this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
|
||||
this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
|
||||
this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
|
||||
|
||||
this.alignment = (ulong)alignment;
|
||||
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<SByte, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<SByte, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
|
||||
}
|
||||
|
||||
public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
inHandle1.Free();
|
||||
inHandle2.Free();
|
||||
outHandle.Free();
|
||||
}
|
||||
|
||||
private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
|
||||
{
|
||||
return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
|
||||
}
|
||||
}
|
||||
|
||||
private struct TestStruct
|
||||
{
|
||||
public Vector128<SByte> _fld1;
|
||||
public Vector128<SByte> _fld2;
|
||||
|
||||
public static TestStruct Create()
|
||||
{
|
||||
var testStruct = new TestStruct();
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref testStruct._fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (SByte)(TestLibrary.Generator.GetSByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
|
||||
return testStruct;
|
||||
}
|
||||
|
||||
public void RunStructFldScenario(SimpleBinaryOpTest__VectorTableLookup_Vector128_SByte testClass)
|
||||
{
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(_fld1, _fld2);
|
||||
|
||||
Unsafe.Write(testClass._dataTable.outArrayPtr, result);
|
||||
testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario_Load(SimpleBinaryOpTest__VectorTableLookup_Vector128_SByte testClass)
|
||||
{
|
||||
fixed (Vector128<SByte>* pFld1 = &_fld1)
|
||||
fixed (Vector128<SByte>* pFld2 = &_fld2)
|
||||
{
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((SByte*)(pFld1)),
|
||||
AdvSimd.LoadVector128((SByte*)(pFld2))
|
||||
);
|
||||
|
||||
Unsafe.Write(testClass._dataTable.outArrayPtr, result);
|
||||
testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly int LargestVectorSize = 16;
|
||||
|
||||
private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
|
||||
private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
|
||||
private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
|
||||
|
||||
private static SByte[] _data1 = new SByte[Op1ElementCount];
|
||||
private static SByte[] _data2 = new SByte[Op2ElementCount];
|
||||
|
||||
private static Vector128<SByte> _clsVar1;
|
||||
private static Vector128<SByte> _clsVar2;
|
||||
|
||||
private Vector128<SByte> _fld1;
|
||||
private Vector128<SByte> _fld2;
|
||||
|
||||
private DataTable _dataTable;
|
||||
|
||||
static SimpleBinaryOpTest__VectorTableLookup_Vector128_SByte()
|
||||
{
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (SByte)(TestLibrary.Generator.GetSByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
}
|
||||
|
||||
public SimpleBinaryOpTest__VectorTableLookup_Vector128_SByte()
|
||||
{
|
||||
Succeeded = true;
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (SByte)(TestLibrary.Generator.GetSByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (SByte)(TestLibrary.Generator.GetSByte() % 20); }
|
||||
_dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize);
|
||||
}
|
||||
|
||||
public bool IsSupported => AdvSimd.Arm64.IsSupported;
|
||||
|
||||
public bool Succeeded { get; set; }
|
||||
|
||||
public void RunBasicScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
|
||||
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(
|
||||
Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
|
||||
Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr)
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunBasicScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
|
||||
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
|
||||
AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunReflectionScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
|
||||
|
||||
var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.VectorTableLookup), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) })
|
||||
.Invoke(null, new object[] {
|
||||
Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
|
||||
Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr)
|
||||
});
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result));
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunReflectionScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
|
||||
|
||||
var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.VectorTableLookup), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) })
|
||||
.Invoke(null, new object[] {
|
||||
AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
|
||||
AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr))
|
||||
});
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result));
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClsVarScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
|
||||
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(
|
||||
_clsVar1,
|
||||
_clsVar2
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClsVarScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
|
||||
|
||||
fixed (Vector128<SByte>* pClsVar1 = &_clsVar1)
|
||||
fixed (Vector128<SByte>* pClsVar2 = &_clsVar2)
|
||||
{
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((SByte*)(pClsVar1)),
|
||||
AdvSimd.LoadVector128((SByte*)(pClsVar2))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunLclVarScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
|
||||
|
||||
var op1 = Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr);
|
||||
var op2 = Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr);
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(op1, op2);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(op1, op2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunLclVarScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
|
||||
|
||||
var op1 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr));
|
||||
var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr));
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(op1, op2);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(op1, op2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassLclFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
|
||||
|
||||
var test = new SimpleBinaryOpTest__VectorTableLookup_Vector128_SByte();
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(test._fld1, test._fld2);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassLclFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
|
||||
|
||||
var test = new SimpleBinaryOpTest__VectorTableLookup_Vector128_SByte();
|
||||
|
||||
fixed (Vector128<SByte>* pFld1 = &test._fld1)
|
||||
fixed (Vector128<SByte>* pFld2 = &test._fld2)
|
||||
{
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((SByte*)(pFld1)),
|
||||
AdvSimd.LoadVector128((SByte*)(pFld2))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunClassFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
|
||||
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(_fld1, _fld2);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
|
||||
|
||||
fixed (Vector128<SByte>* pFld1 = &_fld1)
|
||||
fixed (Vector128<SByte>* pFld2 = &_fld2)
|
||||
{
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((SByte*)(pFld1)),
|
||||
AdvSimd.LoadVector128((SByte*)(pFld2))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunStructLclFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(test._fld1, test._fld2);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructLclFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
var result = AdvSimd.Arm64.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((SByte*)(&test._fld1)),
|
||||
AdvSimd.LoadVector128((SByte*)(&test._fld2))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
test.RunStructFldScenario(this);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
test.RunStructFldScenario_Load(this);
|
||||
}
|
||||
|
||||
public void RunUnsupportedScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
|
||||
|
||||
bool succeeded = false;
|
||||
|
||||
try
|
||||
{
|
||||
RunBasicScenario_UnsafeRead();
|
||||
}
|
||||
catch (PlatformNotSupportedException)
|
||||
{
|
||||
succeeded = true;
|
||||
}
|
||||
|
||||
if (!succeeded)
|
||||
{
|
||||
Succeeded = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateResult(Vector128<SByte> op1, Vector128<SByte> op2, void* result, [CallerMemberName] string method = "")
|
||||
{
|
||||
SByte[] inArray1 = new SByte[Op1ElementCount];
|
||||
SByte[] inArray2 = new SByte[Op2ElementCount];
|
||||
SByte[] outArray = new SByte[RetElementCount];
|
||||
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), op2);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
|
||||
ValidateResult(inArray1, inArray2, outArray, method);
|
||||
}
|
||||
|
||||
private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
|
||||
{
|
||||
SByte[] inArray1 = new SByte[Op1ElementCount];
|
||||
SByte[] inArray2 = new SByte[Op2ElementCount];
|
||||
SByte[] outArray = new SByte[RetElementCount];
|
||||
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
|
||||
ValidateResult(inArray1, inArray2, outArray, method);
|
||||
}
|
||||
|
||||
private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "")
|
||||
{
|
||||
bool succeeded = true;
|
||||
|
||||
if (Helpers.TableVectorLookup(0, right, left) != result[0])
|
||||
{
|
||||
succeeded = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 1; i < RetElementCount; i++)
|
||||
{
|
||||
if (Helpers.TableVectorLookup(i, right, left) != result[i])
|
||||
{
|
||||
succeeded = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!succeeded)
|
||||
{
|
||||
TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.VectorTableLookup)}<SByte>(Vector128<SByte>, Vector128<SByte>): {method} failed:");
|
||||
TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
|
||||
TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
|
||||
TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
|
||||
TestLibrary.TestFramework.LogInformation(string.Empty);
|
||||
|
||||
Succeeded = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,571 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
/******************************************************************************
|
||||
* This file is auto-generated from a template file by the GenerateTests.csx *
|
||||
* script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make *
|
||||
* changes, please update the corresponding template and run according to the *
|
||||
* directions listed in the file. *
|
||||
******************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.Arm;
|
||||
|
||||
namespace JIT.HardwareIntrinsics.Arm
|
||||
{
|
||||
public static partial class Program
|
||||
{
|
||||
private static void VectorTableLookupExtension_Vector128_Byte()
|
||||
{
|
||||
var test = new SimpleTernaryOpTest__VectorTableLookupExtension_Vector128_Byte();
|
||||
|
||||
if (test.IsSupported)
|
||||
{
|
||||
// Validates basic functionality works, using Unsafe.Read
|
||||
test.RunBasicScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates basic functionality works, using Load
|
||||
test.RunBasicScenario_Load();
|
||||
}
|
||||
|
||||
// Validates calling via reflection works, using Unsafe.Read
|
||||
test.RunReflectionScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates calling via reflection works, using Load
|
||||
test.RunReflectionScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing a static member works
|
||||
test.RunClsVarScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing a static member works, using pinning and Load
|
||||
test.RunClsVarScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing a local works, using Unsafe.Read
|
||||
test.RunLclVarScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing a local works, using Load
|
||||
test.RunLclVarScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing the field of a local class works
|
||||
test.RunClassLclFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing the field of a local class works, using pinning and Load
|
||||
test.RunClassLclFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing an instance member of a class works
|
||||
test.RunClassFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing an instance member of a class works, using pinning and Load
|
||||
test.RunClassFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing the field of a local struct works
|
||||
test.RunStructLclFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing the field of a local struct works, using pinning and Load
|
||||
test.RunStructLclFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing an instance member of a struct works
|
||||
test.RunStructFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing an instance member of a struct works, using pinning and Load
|
||||
test.RunStructFldScenario_Load();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Validates we throw on unsupported hardware
|
||||
test.RunUnsupportedScenario();
|
||||
}
|
||||
|
||||
if (!test.Succeeded)
|
||||
{
|
||||
throw new Exception("One or more scenarios did not complete as expected.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed unsafe class SimpleTernaryOpTest__VectorTableLookupExtension_Vector128_Byte
|
||||
{
|
||||
private struct DataTable
|
||||
{
|
||||
private byte[] inArray1;
|
||||
private byte[] inArray2;
|
||||
private byte[] inArray3;
|
||||
private byte[] outArray;
|
||||
|
||||
private GCHandle inHandle1;
|
||||
private GCHandle inHandle2;
|
||||
private GCHandle inHandle3;
|
||||
private GCHandle outHandle;
|
||||
|
||||
private ulong alignment;
|
||||
|
||||
public DataTable(Byte[] inArray1, Byte[] inArray2, Byte[] inArray3, Byte[] outArray, int alignment)
|
||||
{
|
||||
int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
|
||||
int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Byte>();
|
||||
int sizeOfinArray3 = inArray3.Length * Unsafe.SizeOf<Byte>();
|
||||
int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Byte>();
|
||||
if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfinArray3 || (alignment * 2) < sizeOfoutArray)
|
||||
{
|
||||
throw new ArgumentException("Invalid value of alignment");
|
||||
}
|
||||
|
||||
this.inArray1 = new byte[alignment * 2];
|
||||
this.inArray2 = new byte[alignment * 2];
|
||||
this.inArray3 = new byte[alignment * 2];
|
||||
this.outArray = new byte[alignment * 2];
|
||||
|
||||
this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
|
||||
this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
|
||||
this.inHandle3 = GCHandle.Alloc(this.inArray3, GCHandleType.Pinned);
|
||||
this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
|
||||
|
||||
this.alignment = (ulong)alignment;
|
||||
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Byte, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Byte, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray3Ptr), ref Unsafe.As<Byte, byte>(ref inArray3[0]), (uint)sizeOfinArray3);
|
||||
}
|
||||
|
||||
public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
public void* inArray3Ptr => Align((byte*)(inHandle3.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
inHandle1.Free();
|
||||
inHandle2.Free();
|
||||
inHandle3.Free();
|
||||
outHandle.Free();
|
||||
}
|
||||
|
||||
private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
|
||||
{
|
||||
return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
|
||||
}
|
||||
}
|
||||
|
||||
private struct TestStruct
|
||||
{
|
||||
public Vector128<Byte> _fld1;
|
||||
public Vector128<Byte> _fld2;
|
||||
public Vector128<Byte> _fld3;
|
||||
|
||||
public static TestStruct Create()
|
||||
{
|
||||
var testStruct = new TestStruct();
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref testStruct._fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = (Byte)(TestLibrary.Generator.GetByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref testStruct._fld3), ref Unsafe.As<Byte, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
|
||||
return testStruct;
|
||||
}
|
||||
|
||||
public void RunStructFldScenario(SimpleTernaryOpTest__VectorTableLookupExtension_Vector128_Byte testClass)
|
||||
{
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(_fld1, _fld2, _fld3);
|
||||
|
||||
Unsafe.Write(testClass._dataTable.outArrayPtr, result);
|
||||
testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario_Load(SimpleTernaryOpTest__VectorTableLookupExtension_Vector128_Byte testClass)
|
||||
{
|
||||
fixed (Vector128<Byte>* pFld1 = &_fld1)
|
||||
fixed (Vector128<Byte>* pFld2 = &_fld2)
|
||||
fixed (Vector128<Byte>* pFld3 = &_fld3)
|
||||
{
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector128((Byte*)(pFld1)),
|
||||
AdvSimd.LoadVector128((Byte*)(pFld2)),
|
||||
AdvSimd.LoadVector128((Byte*)(pFld3))
|
||||
);
|
||||
|
||||
Unsafe.Write(testClass._dataTable.outArrayPtr, result);
|
||||
testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly int LargestVectorSize = 16;
|
||||
|
||||
private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
|
||||
private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
|
||||
private static readonly int Op3ElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
|
||||
private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
|
||||
|
||||
private static Byte[] _data1 = new Byte[Op1ElementCount];
|
||||
private static Byte[] _data2 = new Byte[Op2ElementCount];
|
||||
private static Byte[] _data3 = new Byte[Op3ElementCount];
|
||||
|
||||
private static Vector128<Byte> _clsVar1;
|
||||
private static Vector128<Byte> _clsVar2;
|
||||
private static Vector128<Byte> _clsVar3;
|
||||
|
||||
private Vector128<Byte> _fld1;
|
||||
private Vector128<Byte> _fld2;
|
||||
private Vector128<Byte> _fld3;
|
||||
|
||||
private DataTable _dataTable;
|
||||
|
||||
static SimpleTernaryOpTest__VectorTableLookupExtension_Vector128_Byte()
|
||||
{
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = (Byte)(TestLibrary.Generator.GetByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar3), ref Unsafe.As<Byte, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
}
|
||||
|
||||
public SimpleTernaryOpTest__VectorTableLookupExtension_Vector128_Byte()
|
||||
{
|
||||
Succeeded = true;
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = (Byte)(TestLibrary.Generator.GetByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld3), ref Unsafe.As<Byte, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
|
||||
for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = (Byte)(TestLibrary.Generator.GetByte() % 20); }
|
||||
_dataTable = new DataTable(_data1, _data2, _data3, new Byte[RetElementCount], LargestVectorSize);
|
||||
}
|
||||
|
||||
public bool IsSupported => AdvSimd.Arm64.IsSupported;
|
||||
|
||||
public bool Succeeded { get; set; }
|
||||
|
||||
public void RunBasicScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
|
||||
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(
|
||||
Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
|
||||
Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr),
|
||||
Unsafe.Read<Vector128<Byte>>(_dataTable.inArray3Ptr)
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunBasicScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
|
||||
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
|
||||
AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr)),
|
||||
AdvSimd.LoadVector128((Byte*)(_dataTable.inArray3Ptr))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunReflectionScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
|
||||
|
||||
var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.VectorTableLookupExtension), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>), typeof(Vector128<Byte>) })
|
||||
.Invoke(null, new object[] {
|
||||
Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
|
||||
Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr),
|
||||
Unsafe.Read<Vector128<Byte>>(_dataTable.inArray3Ptr)
|
||||
});
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result));
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunReflectionScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
|
||||
|
||||
var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.VectorTableLookupExtension), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>), typeof(Vector128<Byte>) })
|
||||
.Invoke(null, new object[] {
|
||||
AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
|
||||
AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr)),
|
||||
AdvSimd.LoadVector128((Byte*)(_dataTable.inArray3Ptr))
|
||||
});
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result));
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClsVarScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
|
||||
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(
|
||||
_clsVar1,
|
||||
_clsVar2,
|
||||
_clsVar3
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_clsVar1, _clsVar2, _clsVar3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClsVarScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
|
||||
|
||||
fixed (Vector128<Byte>* pClsVar1 = &_clsVar1)
|
||||
fixed (Vector128<Byte>* pClsVar2 = &_clsVar2)
|
||||
fixed (Vector128<Byte>* pClsVar3 = &_clsVar3)
|
||||
{
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector128((Byte*)(pClsVar1)),
|
||||
AdvSimd.LoadVector128((Byte*)(pClsVar2)),
|
||||
AdvSimd.LoadVector128((Byte*)(pClsVar3))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_clsVar1, _clsVar2, _clsVar3, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunLclVarScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
|
||||
|
||||
var op1 = Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr);
|
||||
var op2 = Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr);
|
||||
var op3 = Unsafe.Read<Vector128<Byte>>(_dataTable.inArray3Ptr);
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(op1, op2, op3);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(op1, op2, op3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunLclVarScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
|
||||
|
||||
var op1 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr));
|
||||
var op2 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr));
|
||||
var op3 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray3Ptr));
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(op1, op2, op3);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(op1, op2, op3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassLclFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
|
||||
|
||||
var test = new SimpleTernaryOpTest__VectorTableLookupExtension_Vector128_Byte();
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(test._fld1, test._fld2, test._fld3);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassLclFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
|
||||
|
||||
var test = new SimpleTernaryOpTest__VectorTableLookupExtension_Vector128_Byte();
|
||||
|
||||
fixed (Vector128<Byte>* pFld1 = &test._fld1)
|
||||
fixed (Vector128<Byte>* pFld2 = &test._fld2)
|
||||
fixed (Vector128<Byte>* pFld3 = &test._fld3)
|
||||
{
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector128((Byte*)(pFld1)),
|
||||
AdvSimd.LoadVector128((Byte*)(pFld2)),
|
||||
AdvSimd.LoadVector128((Byte*)(pFld3))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunClassFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
|
||||
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(_fld1, _fld2, _fld3);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
|
||||
|
||||
fixed (Vector128<Byte>* pFld1 = &_fld1)
|
||||
fixed (Vector128<Byte>* pFld2 = &_fld2)
|
||||
fixed (Vector128<Byte>* pFld3 = &_fld3)
|
||||
{
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector128((Byte*)(pFld1)),
|
||||
AdvSimd.LoadVector128((Byte*)(pFld2)),
|
||||
AdvSimd.LoadVector128((Byte*)(pFld3))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunStructLclFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(test._fld1, test._fld2, test._fld3);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructLclFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector128((Byte*)(&test._fld1)),
|
||||
AdvSimd.LoadVector128((Byte*)(&test._fld2)),
|
||||
AdvSimd.LoadVector128((Byte*)(&test._fld3))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
test.RunStructFldScenario(this);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
test.RunStructFldScenario_Load(this);
|
||||
}
|
||||
|
||||
public void RunUnsupportedScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
|
||||
|
||||
bool succeeded = false;
|
||||
|
||||
try
|
||||
{
|
||||
RunBasicScenario_UnsafeRead();
|
||||
}
|
||||
catch (PlatformNotSupportedException)
|
||||
{
|
||||
succeeded = true;
|
||||
}
|
||||
|
||||
if (!succeeded)
|
||||
{
|
||||
Succeeded = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateResult(Vector128<Byte> op1, Vector128<Byte> op2, Vector128<Byte> op3, void* result, [CallerMemberName] string method = "")
|
||||
{
|
||||
Byte[] inArray1 = new Byte[Op1ElementCount];
|
||||
Byte[] inArray2 = new Byte[Op2ElementCount];
|
||||
Byte[] inArray3 = new Byte[Op3ElementCount];
|
||||
Byte[] outArray = new Byte[RetElementCount];
|
||||
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), op2);
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray3[0]), op3);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
|
||||
ValidateResult(inArray1, inArray2, inArray3, outArray, method);
|
||||
}
|
||||
|
||||
private void ValidateResult(void* op1, void* op2, void* op3, void* result, [CallerMemberName] string method = "")
|
||||
{
|
||||
Byte[] inArray1 = new Byte[Op1ElementCount];
|
||||
Byte[] inArray2 = new Byte[Op2ElementCount];
|
||||
Byte[] inArray3 = new Byte[Op3ElementCount];
|
||||
Byte[] outArray = new Byte[RetElementCount];
|
||||
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray3[0]), ref Unsafe.AsRef<byte>(op3), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
|
||||
ValidateResult(inArray1, inArray2, inArray3, outArray, method);
|
||||
}
|
||||
|
||||
private void ValidateResult(Byte[] firstOp, Byte[] secondOp, Byte[] thirdOp, Byte[] result, [CallerMemberName] string method = "")
|
||||
{
|
||||
bool succeeded = true;
|
||||
|
||||
for (var i = 0; i < RetElementCount; i++)
|
||||
{
|
||||
if (Helpers.TableVectorExtension(i, firstOp, thirdOp, secondOp) != result[i])
|
||||
{
|
||||
succeeded = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!succeeded)
|
||||
{
|
||||
TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.VectorTableLookupExtension)}<Byte>(Vector128<Byte>, Vector128<Byte>, Vector128<Byte>): {method} failed:");
|
||||
TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})");
|
||||
TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})");
|
||||
TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})");
|
||||
TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
|
||||
TestLibrary.TestFramework.LogInformation(string.Empty);
|
||||
|
||||
Succeeded = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,571 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
/******************************************************************************
|
||||
* This file is auto-generated from a template file by the GenerateTests.csx *
|
||||
* script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make *
|
||||
* changes, please update the corresponding template and run according to the *
|
||||
* directions listed in the file. *
|
||||
******************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.Arm;
|
||||
|
||||
namespace JIT.HardwareIntrinsics.Arm
|
||||
{
|
||||
public static partial class Program
|
||||
{
|
||||
private static void VectorTableLookupExtension_Vector128_SByte()
|
||||
{
|
||||
var test = new SimpleTernaryOpTest__VectorTableLookupExtension_Vector128_SByte();
|
||||
|
||||
if (test.IsSupported)
|
||||
{
|
||||
// Validates basic functionality works, using Unsafe.Read
|
||||
test.RunBasicScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates basic functionality works, using Load
|
||||
test.RunBasicScenario_Load();
|
||||
}
|
||||
|
||||
// Validates calling via reflection works, using Unsafe.Read
|
||||
test.RunReflectionScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates calling via reflection works, using Load
|
||||
test.RunReflectionScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing a static member works
|
||||
test.RunClsVarScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing a static member works, using pinning and Load
|
||||
test.RunClsVarScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing a local works, using Unsafe.Read
|
||||
test.RunLclVarScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing a local works, using Load
|
||||
test.RunLclVarScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing the field of a local class works
|
||||
test.RunClassLclFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing the field of a local class works, using pinning and Load
|
||||
test.RunClassLclFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing an instance member of a class works
|
||||
test.RunClassFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing an instance member of a class works, using pinning and Load
|
||||
test.RunClassFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing the field of a local struct works
|
||||
test.RunStructLclFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing the field of a local struct works, using pinning and Load
|
||||
test.RunStructLclFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing an instance member of a struct works
|
||||
test.RunStructFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing an instance member of a struct works, using pinning and Load
|
||||
test.RunStructFldScenario_Load();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Validates we throw on unsupported hardware
|
||||
test.RunUnsupportedScenario();
|
||||
}
|
||||
|
||||
if (!test.Succeeded)
|
||||
{
|
||||
throw new Exception("One or more scenarios did not complete as expected.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed unsafe class SimpleTernaryOpTest__VectorTableLookupExtension_Vector128_SByte
|
||||
{
|
||||
private struct DataTable
|
||||
{
|
||||
private byte[] inArray1;
|
||||
private byte[] inArray2;
|
||||
private byte[] inArray3;
|
||||
private byte[] outArray;
|
||||
|
||||
private GCHandle inHandle1;
|
||||
private GCHandle inHandle2;
|
||||
private GCHandle inHandle3;
|
||||
private GCHandle outHandle;
|
||||
|
||||
private ulong alignment;
|
||||
|
||||
public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] inArray3, SByte[] outArray, int alignment)
|
||||
{
|
||||
int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
|
||||
int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<SByte>();
|
||||
int sizeOfinArray3 = inArray3.Length * Unsafe.SizeOf<SByte>();
|
||||
int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<SByte>();
|
||||
if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfinArray3 || (alignment * 2) < sizeOfoutArray)
|
||||
{
|
||||
throw new ArgumentException("Invalid value of alignment");
|
||||
}
|
||||
|
||||
this.inArray1 = new byte[alignment * 2];
|
||||
this.inArray2 = new byte[alignment * 2];
|
||||
this.inArray3 = new byte[alignment * 2];
|
||||
this.outArray = new byte[alignment * 2];
|
||||
|
||||
this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
|
||||
this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
|
||||
this.inHandle3 = GCHandle.Alloc(this.inArray3, GCHandleType.Pinned);
|
||||
this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
|
||||
|
||||
this.alignment = (ulong)alignment;
|
||||
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<SByte, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<SByte, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray3Ptr), ref Unsafe.As<SByte, byte>(ref inArray3[0]), (uint)sizeOfinArray3);
|
||||
}
|
||||
|
||||
public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
public void* inArray3Ptr => Align((byte*)(inHandle3.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
inHandle1.Free();
|
||||
inHandle2.Free();
|
||||
inHandle3.Free();
|
||||
outHandle.Free();
|
||||
}
|
||||
|
||||
private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
|
||||
{
|
||||
return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
|
||||
}
|
||||
}
|
||||
|
||||
private struct TestStruct
|
||||
{
|
||||
public Vector128<SByte> _fld1;
|
||||
public Vector128<SByte> _fld2;
|
||||
public Vector128<SByte> _fld3;
|
||||
|
||||
public static TestStruct Create()
|
||||
{
|
||||
var testStruct = new TestStruct();
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref testStruct._fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = (SByte)(TestLibrary.Generator.GetSByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref testStruct._fld3), ref Unsafe.As<SByte, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
|
||||
return testStruct;
|
||||
}
|
||||
|
||||
public void RunStructFldScenario(SimpleTernaryOpTest__VectorTableLookupExtension_Vector128_SByte testClass)
|
||||
{
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(_fld1, _fld2, _fld3);
|
||||
|
||||
Unsafe.Write(testClass._dataTable.outArrayPtr, result);
|
||||
testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario_Load(SimpleTernaryOpTest__VectorTableLookupExtension_Vector128_SByte testClass)
|
||||
{
|
||||
fixed (Vector128<SByte>* pFld1 = &_fld1)
|
||||
fixed (Vector128<SByte>* pFld2 = &_fld2)
|
||||
fixed (Vector128<SByte>* pFld3 = &_fld3)
|
||||
{
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector128((SByte*)(pFld1)),
|
||||
AdvSimd.LoadVector128((SByte*)(pFld2)),
|
||||
AdvSimd.LoadVector128((SByte*)(pFld3))
|
||||
);
|
||||
|
||||
Unsafe.Write(testClass._dataTable.outArrayPtr, result);
|
||||
testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly int LargestVectorSize = 16;
|
||||
|
||||
private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
|
||||
private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
|
||||
private static readonly int Op3ElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
|
||||
private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
|
||||
|
||||
private static SByte[] _data1 = new SByte[Op1ElementCount];
|
||||
private static SByte[] _data2 = new SByte[Op2ElementCount];
|
||||
private static SByte[] _data3 = new SByte[Op3ElementCount];
|
||||
|
||||
private static Vector128<SByte> _clsVar1;
|
||||
private static Vector128<SByte> _clsVar2;
|
||||
private static Vector128<SByte> _clsVar3;
|
||||
|
||||
private Vector128<SByte> _fld1;
|
||||
private Vector128<SByte> _fld2;
|
||||
private Vector128<SByte> _fld3;
|
||||
|
||||
private DataTable _dataTable;
|
||||
|
||||
static SimpleTernaryOpTest__VectorTableLookupExtension_Vector128_SByte()
|
||||
{
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = (SByte)(TestLibrary.Generator.GetSByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar3), ref Unsafe.As<SByte, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
}
|
||||
|
||||
public SimpleTernaryOpTest__VectorTableLookupExtension_Vector128_SByte()
|
||||
{
|
||||
Succeeded = true;
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = (SByte)(TestLibrary.Generator.GetSByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld3), ref Unsafe.As<SByte, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
|
||||
for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = (SByte)(TestLibrary.Generator.GetSByte() % 20); }
|
||||
_dataTable = new DataTable(_data1, _data2, _data3, new SByte[RetElementCount], LargestVectorSize);
|
||||
}
|
||||
|
||||
public bool IsSupported => AdvSimd.Arm64.IsSupported;
|
||||
|
||||
public bool Succeeded { get; set; }
|
||||
|
||||
public void RunBasicScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
|
||||
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(
|
||||
Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
|
||||
Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr),
|
||||
Unsafe.Read<Vector128<SByte>>(_dataTable.inArray3Ptr)
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunBasicScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
|
||||
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
|
||||
AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)),
|
||||
AdvSimd.LoadVector128((SByte*)(_dataTable.inArray3Ptr))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunReflectionScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
|
||||
|
||||
var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.VectorTableLookupExtension), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>), typeof(Vector128<SByte>) })
|
||||
.Invoke(null, new object[] {
|
||||
Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
|
||||
Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr),
|
||||
Unsafe.Read<Vector128<SByte>>(_dataTable.inArray3Ptr)
|
||||
});
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result));
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunReflectionScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
|
||||
|
||||
var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.VectorTableLookupExtension), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>), typeof(Vector128<SByte>) })
|
||||
.Invoke(null, new object[] {
|
||||
AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
|
||||
AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)),
|
||||
AdvSimd.LoadVector128((SByte*)(_dataTable.inArray3Ptr))
|
||||
});
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result));
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClsVarScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
|
||||
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(
|
||||
_clsVar1,
|
||||
_clsVar2,
|
||||
_clsVar3
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_clsVar1, _clsVar2, _clsVar3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClsVarScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
|
||||
|
||||
fixed (Vector128<SByte>* pClsVar1 = &_clsVar1)
|
||||
fixed (Vector128<SByte>* pClsVar2 = &_clsVar2)
|
||||
fixed (Vector128<SByte>* pClsVar3 = &_clsVar3)
|
||||
{
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector128((SByte*)(pClsVar1)),
|
||||
AdvSimd.LoadVector128((SByte*)(pClsVar2)),
|
||||
AdvSimd.LoadVector128((SByte*)(pClsVar3))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_clsVar1, _clsVar2, _clsVar3, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunLclVarScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
|
||||
|
||||
var op1 = Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr);
|
||||
var op2 = Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr);
|
||||
var op3 = Unsafe.Read<Vector128<SByte>>(_dataTable.inArray3Ptr);
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(op1, op2, op3);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(op1, op2, op3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunLclVarScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
|
||||
|
||||
var op1 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr));
|
||||
var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr));
|
||||
var op3 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray3Ptr));
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(op1, op2, op3);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(op1, op2, op3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassLclFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
|
||||
|
||||
var test = new SimpleTernaryOpTest__VectorTableLookupExtension_Vector128_SByte();
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(test._fld1, test._fld2, test._fld3);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassLclFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
|
||||
|
||||
var test = new SimpleTernaryOpTest__VectorTableLookupExtension_Vector128_SByte();
|
||||
|
||||
fixed (Vector128<SByte>* pFld1 = &test._fld1)
|
||||
fixed (Vector128<SByte>* pFld2 = &test._fld2)
|
||||
fixed (Vector128<SByte>* pFld3 = &test._fld3)
|
||||
{
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector128((SByte*)(pFld1)),
|
||||
AdvSimd.LoadVector128((SByte*)(pFld2)),
|
||||
AdvSimd.LoadVector128((SByte*)(pFld3))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunClassFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
|
||||
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(_fld1, _fld2, _fld3);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
|
||||
|
||||
fixed (Vector128<SByte>* pFld1 = &_fld1)
|
||||
fixed (Vector128<SByte>* pFld2 = &_fld2)
|
||||
fixed (Vector128<SByte>* pFld3 = &_fld3)
|
||||
{
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector128((SByte*)(pFld1)),
|
||||
AdvSimd.LoadVector128((SByte*)(pFld2)),
|
||||
AdvSimd.LoadVector128((SByte*)(pFld3))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunStructLclFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(test._fld1, test._fld2, test._fld3);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructLclFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
var result = AdvSimd.Arm64.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector128((SByte*)(&test._fld1)),
|
||||
AdvSimd.LoadVector128((SByte*)(&test._fld2)),
|
||||
AdvSimd.LoadVector128((SByte*)(&test._fld3))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
test.RunStructFldScenario(this);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
test.RunStructFldScenario_Load(this);
|
||||
}
|
||||
|
||||
public void RunUnsupportedScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
|
||||
|
||||
bool succeeded = false;
|
||||
|
||||
try
|
||||
{
|
||||
RunBasicScenario_UnsafeRead();
|
||||
}
|
||||
catch (PlatformNotSupportedException)
|
||||
{
|
||||
succeeded = true;
|
||||
}
|
||||
|
||||
if (!succeeded)
|
||||
{
|
||||
Succeeded = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateResult(Vector128<SByte> op1, Vector128<SByte> op2, Vector128<SByte> op3, void* result, [CallerMemberName] string method = "")
|
||||
{
|
||||
SByte[] inArray1 = new SByte[Op1ElementCount];
|
||||
SByte[] inArray2 = new SByte[Op2ElementCount];
|
||||
SByte[] inArray3 = new SByte[Op3ElementCount];
|
||||
SByte[] outArray = new SByte[RetElementCount];
|
||||
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), op2);
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray3[0]), op3);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
|
||||
ValidateResult(inArray1, inArray2, inArray3, outArray, method);
|
||||
}
|
||||
|
||||
private void ValidateResult(void* op1, void* op2, void* op3, void* result, [CallerMemberName] string method = "")
|
||||
{
|
||||
SByte[] inArray1 = new SByte[Op1ElementCount];
|
||||
SByte[] inArray2 = new SByte[Op2ElementCount];
|
||||
SByte[] inArray3 = new SByte[Op3ElementCount];
|
||||
SByte[] outArray = new SByte[RetElementCount];
|
||||
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray3[0]), ref Unsafe.AsRef<byte>(op3), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
|
||||
ValidateResult(inArray1, inArray2, inArray3, outArray, method);
|
||||
}
|
||||
|
||||
private void ValidateResult(SByte[] firstOp, SByte[] secondOp, SByte[] thirdOp, SByte[] result, [CallerMemberName] string method = "")
|
||||
{
|
||||
bool succeeded = true;
|
||||
|
||||
for (var i = 0; i < RetElementCount; i++)
|
||||
{
|
||||
if (Helpers.TableVectorExtension(i, firstOp, thirdOp, secondOp) != result[i])
|
||||
{
|
||||
succeeded = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!succeeded)
|
||||
{
|
||||
TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.VectorTableLookupExtension)}<SByte>(Vector128<SByte>, Vector128<SByte>, Vector128<SByte>): {method} failed:");
|
||||
TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})");
|
||||
TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})");
|
||||
TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})");
|
||||
TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
|
||||
TestLibrary.TestFramework.LogInformation(string.Empty);
|
||||
|
||||
Succeeded = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -560,6 +560,10 @@
|
|||
<Compile Include="SubtractScalar.Vector64.Int64.cs" />
|
||||
<Compile Include="SubtractScalar.Vector64.Single.cs" />
|
||||
<Compile Include="SubtractScalar.Vector64.UInt64.cs" />
|
||||
<Compile Include="VectorTableLookup.Vector64.Byte.cs" />
|
||||
<Compile Include="VectorTableLookup.Vector64.SByte.cs" />
|
||||
<Compile Include="VectorTableLookupExtension.Vector64.Byte.cs" />
|
||||
<Compile Include="VectorTableLookupExtension.Vector64.SByte.cs" />
|
||||
<Compile Include="Xor.Vector64.Byte.cs" />
|
||||
<Compile Include="Xor.Vector64.Double.cs" />
|
||||
<Compile Include="Xor.Vector64.Int16.cs" />
|
||||
|
|
|
@ -560,6 +560,10 @@
|
|||
<Compile Include="SubtractScalar.Vector64.Int64.cs" />
|
||||
<Compile Include="SubtractScalar.Vector64.Single.cs" />
|
||||
<Compile Include="SubtractScalar.Vector64.UInt64.cs" />
|
||||
<Compile Include="VectorTableLookup.Vector64.Byte.cs" />
|
||||
<Compile Include="VectorTableLookup.Vector64.SByte.cs" />
|
||||
<Compile Include="VectorTableLookupExtension.Vector64.Byte.cs" />
|
||||
<Compile Include="VectorTableLookupExtension.Vector64.SByte.cs" />
|
||||
<Compile Include="Xor.Vector64.Byte.cs" />
|
||||
<Compile Include="Xor.Vector64.Double.cs" />
|
||||
<Compile Include="Xor.Vector64.Int16.cs" />
|
||||
|
|
|
@ -564,6 +564,10 @@ namespace JIT.HardwareIntrinsics.Arm
|
|||
["SubtractScalar.Vector64.Int64"] = SubtractScalar_Vector64_Int64,
|
||||
["SubtractScalar.Vector64.Single"] = SubtractScalar_Vector64_Single,
|
||||
["SubtractScalar.Vector64.UInt64"] = SubtractScalar_Vector64_UInt64,
|
||||
["VectorTableLookup.Vector64.Byte"] = VectorTableLookup_Vector64_Byte,
|
||||
["VectorTableLookup.Vector64.SByte"] = VectorTableLookup_Vector64_SByte,
|
||||
["VectorTableLookupExtension.Vector64.Byte"] = VectorTableLookupExtension_Vector64_Byte,
|
||||
["VectorTableLookupExtension.Vector64.SByte"] = VectorTableLookupExtension_Vector64_SByte,
|
||||
["Xor.Vector64.Byte"] = Xor_Vector64_Byte,
|
||||
["Xor.Vector64.Double"] = Xor_Vector64_Double,
|
||||
["Xor.Vector64.Int16"] = Xor_Vector64_Int16,
|
||||
|
|
|
@ -0,0 +1,537 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
/******************************************************************************
|
||||
* This file is auto-generated from a template file by the GenerateTests.csx *
|
||||
* script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make *
|
||||
* changes, please update the corresponding template and run according to the *
|
||||
* directions listed in the file. *
|
||||
******************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.Arm;
|
||||
|
||||
namespace JIT.HardwareIntrinsics.Arm
|
||||
{
|
||||
public static partial class Program
|
||||
{
|
||||
private static void VectorTableLookup_Vector64_Byte()
|
||||
{
|
||||
var test = new SimpleBinaryOpTest__VectorTableLookup_Vector64_Byte();
|
||||
|
||||
if (test.IsSupported)
|
||||
{
|
||||
// Validates basic functionality works, using Unsafe.Read
|
||||
test.RunBasicScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates basic functionality works, using Load
|
||||
test.RunBasicScenario_Load();
|
||||
}
|
||||
|
||||
// Validates calling via reflection works, using Unsafe.Read
|
||||
test.RunReflectionScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates calling via reflection works, using Load
|
||||
test.RunReflectionScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing a static member works
|
||||
test.RunClsVarScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing a static member works, using pinning and Load
|
||||
test.RunClsVarScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing a local works, using Unsafe.Read
|
||||
test.RunLclVarScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing a local works, using Load
|
||||
test.RunLclVarScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing the field of a local class works
|
||||
test.RunClassLclFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing the field of a local class works, using pinning and Load
|
||||
test.RunClassLclFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing an instance member of a class works
|
||||
test.RunClassFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing an instance member of a class works, using pinning and Load
|
||||
test.RunClassFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing the field of a local struct works
|
||||
test.RunStructLclFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing the field of a local struct works, using pinning and Load
|
||||
test.RunStructLclFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing an instance member of a struct works
|
||||
test.RunStructFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing an instance member of a struct works, using pinning and Load
|
||||
test.RunStructFldScenario_Load();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Validates we throw on unsupported hardware
|
||||
test.RunUnsupportedScenario();
|
||||
}
|
||||
|
||||
if (!test.Succeeded)
|
||||
{
|
||||
throw new Exception("One or more scenarios did not complete as expected.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed unsafe class SimpleBinaryOpTest__VectorTableLookup_Vector64_Byte
|
||||
{
|
||||
private struct DataTable
|
||||
{
|
||||
private byte[] inArray1;
|
||||
private byte[] inArray2;
|
||||
private byte[] outArray;
|
||||
|
||||
private GCHandle inHandle1;
|
||||
private GCHandle inHandle2;
|
||||
private GCHandle outHandle;
|
||||
|
||||
private ulong alignment;
|
||||
|
||||
public DataTable(Byte[] inArray1, Byte[] inArray2, Byte[] outArray, int alignment)
|
||||
{
|
||||
int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
|
||||
int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Byte>();
|
||||
int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Byte>();
|
||||
if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
|
||||
{
|
||||
throw new ArgumentException("Invalid value of alignment");
|
||||
}
|
||||
|
||||
this.inArray1 = new byte[alignment * 2];
|
||||
this.inArray2 = new byte[alignment * 2];
|
||||
this.outArray = new byte[alignment * 2];
|
||||
|
||||
this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
|
||||
this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
|
||||
this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
|
||||
|
||||
this.alignment = (ulong)alignment;
|
||||
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Byte, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Byte, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
|
||||
}
|
||||
|
||||
public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
inHandle1.Free();
|
||||
inHandle2.Free();
|
||||
outHandle.Free();
|
||||
}
|
||||
|
||||
private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
|
||||
{
|
||||
return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
|
||||
}
|
||||
}
|
||||
|
||||
private struct TestStruct
|
||||
{
|
||||
public Vector128<Byte> _fld1;
|
||||
public Vector64<Byte> _fld2;
|
||||
|
||||
public static TestStruct Create()
|
||||
{
|
||||
var testStruct = new TestStruct();
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref testStruct._fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (Byte)(TestLibrary.Generator.GetByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
|
||||
|
||||
return testStruct;
|
||||
}
|
||||
|
||||
public void RunStructFldScenario(SimpleBinaryOpTest__VectorTableLookup_Vector64_Byte testClass)
|
||||
{
|
||||
var result = AdvSimd.VectorTableLookup(_fld1, _fld2);
|
||||
|
||||
Unsafe.Write(testClass._dataTable.outArrayPtr, result);
|
||||
testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario_Load(SimpleBinaryOpTest__VectorTableLookup_Vector64_Byte testClass)
|
||||
{
|
||||
fixed (Vector128<Byte>* pFld1 = &_fld1)
|
||||
fixed (Vector64<Byte>* pFld2 = &_fld2)
|
||||
{
|
||||
var result = AdvSimd.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((Byte*)(pFld1)),
|
||||
AdvSimd.LoadVector64((Byte*)(pFld2))
|
||||
);
|
||||
|
||||
Unsafe.Write(testClass._dataTable.outArrayPtr, result);
|
||||
testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly int LargestVectorSize = 16;
|
||||
|
||||
private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
|
||||
private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
|
||||
private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
|
||||
|
||||
private static Byte[] _data1 = new Byte[Op1ElementCount];
|
||||
private static Byte[] _data2 = new Byte[Op2ElementCount];
|
||||
|
||||
private static Vector128<Byte> _clsVar1;
|
||||
private static Vector64<Byte> _clsVar2;
|
||||
|
||||
private Vector128<Byte> _fld1;
|
||||
private Vector64<Byte> _fld2;
|
||||
|
||||
private DataTable _dataTable;
|
||||
|
||||
static SimpleBinaryOpTest__VectorTableLookup_Vector64_Byte()
|
||||
{
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (Byte)(TestLibrary.Generator.GetByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
|
||||
}
|
||||
|
||||
public SimpleBinaryOpTest__VectorTableLookup_Vector64_Byte()
|
||||
{
|
||||
Succeeded = true;
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (Byte)(TestLibrary.Generator.GetByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (Byte)(TestLibrary.Generator.GetByte() % 20); }
|
||||
_dataTable = new DataTable(_data1, _data2, new Byte[RetElementCount], LargestVectorSize);
|
||||
}
|
||||
|
||||
public bool IsSupported => AdvSimd.IsSupported;
|
||||
|
||||
public bool Succeeded { get; set; }
|
||||
|
||||
public void RunBasicScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
|
||||
|
||||
var result = AdvSimd.VectorTableLookup(
|
||||
Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
|
||||
Unsafe.Read<Vector64<Byte>>(_dataTable.inArray2Ptr)
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunBasicScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
|
||||
|
||||
var result = AdvSimd.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
|
||||
AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunReflectionScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
|
||||
|
||||
var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.VectorTableLookup), new Type[] { typeof(Vector128<Byte>), typeof(Vector64<Byte>) })
|
||||
.Invoke(null, new object[] {
|
||||
Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
|
||||
Unsafe.Read<Vector64<Byte>>(_dataTable.inArray2Ptr)
|
||||
});
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Byte>)(result));
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunReflectionScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
|
||||
|
||||
var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.VectorTableLookup), new Type[] { typeof(Vector128<Byte>), typeof(Vector64<Byte>) })
|
||||
.Invoke(null, new object[] {
|
||||
AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
|
||||
AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr))
|
||||
});
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Byte>)(result));
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClsVarScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
|
||||
|
||||
var result = AdvSimd.VectorTableLookup(
|
||||
_clsVar1,
|
||||
_clsVar2
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClsVarScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
|
||||
|
||||
fixed (Vector128<Byte>* pClsVar1 = &_clsVar1)
|
||||
fixed (Vector64<Byte>* pClsVar2 = &_clsVar2)
|
||||
{
|
||||
var result = AdvSimd.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((Byte*)(pClsVar1)),
|
||||
AdvSimd.LoadVector64((Byte*)(pClsVar2))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunLclVarScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
|
||||
|
||||
var op1 = Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr);
|
||||
var op2 = Unsafe.Read<Vector64<Byte>>(_dataTable.inArray2Ptr);
|
||||
var result = AdvSimd.VectorTableLookup(op1, op2);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(op1, op2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunLclVarScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
|
||||
|
||||
var op1 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr));
|
||||
var op2 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr));
|
||||
var result = AdvSimd.VectorTableLookup(op1, op2);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(op1, op2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassLclFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
|
||||
|
||||
var test = new SimpleBinaryOpTest__VectorTableLookup_Vector64_Byte();
|
||||
var result = AdvSimd.VectorTableLookup(test._fld1, test._fld2);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassLclFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
|
||||
|
||||
var test = new SimpleBinaryOpTest__VectorTableLookup_Vector64_Byte();
|
||||
|
||||
fixed (Vector128<Byte>* pFld1 = &test._fld1)
|
||||
fixed (Vector64<Byte>* pFld2 = &test._fld2)
|
||||
{
|
||||
var result = AdvSimd.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((Byte*)(pFld1)),
|
||||
AdvSimd.LoadVector64((Byte*)(pFld2))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunClassFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
|
||||
|
||||
var result = AdvSimd.VectorTableLookup(_fld1, _fld2);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
|
||||
|
||||
fixed (Vector128<Byte>* pFld1 = &_fld1)
|
||||
fixed (Vector64<Byte>* pFld2 = &_fld2)
|
||||
{
|
||||
var result = AdvSimd.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((Byte*)(pFld1)),
|
||||
AdvSimd.LoadVector64((Byte*)(pFld2))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunStructLclFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
var result = AdvSimd.VectorTableLookup(test._fld1, test._fld2);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructLclFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
var result = AdvSimd.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((Byte*)(&test._fld1)),
|
||||
AdvSimd.LoadVector64((Byte*)(&test._fld2))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
test.RunStructFldScenario(this);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
test.RunStructFldScenario_Load(this);
|
||||
}
|
||||
|
||||
public void RunUnsupportedScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
|
||||
|
||||
bool succeeded = false;
|
||||
|
||||
try
|
||||
{
|
||||
RunBasicScenario_UnsafeRead();
|
||||
}
|
||||
catch (PlatformNotSupportedException)
|
||||
{
|
||||
succeeded = true;
|
||||
}
|
||||
|
||||
if (!succeeded)
|
||||
{
|
||||
Succeeded = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateResult(Vector128<Byte> op1, Vector64<Byte> op2, void* result, [CallerMemberName] string method = "")
|
||||
{
|
||||
Byte[] inArray1 = new Byte[Op1ElementCount];
|
||||
Byte[] inArray2 = new Byte[Op2ElementCount];
|
||||
Byte[] outArray = new Byte[RetElementCount];
|
||||
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), op2);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
|
||||
|
||||
ValidateResult(inArray1, inArray2, outArray, method);
|
||||
}
|
||||
|
||||
private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
|
||||
{
|
||||
Byte[] inArray1 = new Byte[Op1ElementCount];
|
||||
Byte[] inArray2 = new Byte[Op2ElementCount];
|
||||
Byte[] outArray = new Byte[RetElementCount];
|
||||
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Byte>>());
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
|
||||
|
||||
ValidateResult(inArray1, inArray2, outArray, method);
|
||||
}
|
||||
|
||||
private void ValidateResult(Byte[] left, Byte[] right, Byte[] result, [CallerMemberName] string method = "")
|
||||
{
|
||||
bool succeeded = true;
|
||||
|
||||
if (Helpers.TableVectorLookup(0, right, left) != result[0])
|
||||
{
|
||||
succeeded = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 1; i < RetElementCount; i++)
|
||||
{
|
||||
if (Helpers.TableVectorLookup(i, right, left) != result[i])
|
||||
{
|
||||
succeeded = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!succeeded)
|
||||
{
|
||||
TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.VectorTableLookup)}<Byte>(Vector128<Byte>, Vector64<Byte>): {method} failed:");
|
||||
TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
|
||||
TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
|
||||
TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
|
||||
TestLibrary.TestFramework.LogInformation(string.Empty);
|
||||
|
||||
Succeeded = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,537 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
/******************************************************************************
|
||||
* This file is auto-generated from a template file by the GenerateTests.csx *
|
||||
* script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make *
|
||||
* changes, please update the corresponding template and run according to the *
|
||||
* directions listed in the file. *
|
||||
******************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.Arm;
|
||||
|
||||
namespace JIT.HardwareIntrinsics.Arm
|
||||
{
|
||||
public static partial class Program
|
||||
{
|
||||
private static void VectorTableLookup_Vector64_SByte()
|
||||
{
|
||||
var test = new SimpleBinaryOpTest__VectorTableLookup_Vector64_SByte();
|
||||
|
||||
if (test.IsSupported)
|
||||
{
|
||||
// Validates basic functionality works, using Unsafe.Read
|
||||
test.RunBasicScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates basic functionality works, using Load
|
||||
test.RunBasicScenario_Load();
|
||||
}
|
||||
|
||||
// Validates calling via reflection works, using Unsafe.Read
|
||||
test.RunReflectionScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates calling via reflection works, using Load
|
||||
test.RunReflectionScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing a static member works
|
||||
test.RunClsVarScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing a static member works, using pinning and Load
|
||||
test.RunClsVarScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing a local works, using Unsafe.Read
|
||||
test.RunLclVarScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing a local works, using Load
|
||||
test.RunLclVarScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing the field of a local class works
|
||||
test.RunClassLclFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing the field of a local class works, using pinning and Load
|
||||
test.RunClassLclFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing an instance member of a class works
|
||||
test.RunClassFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing an instance member of a class works, using pinning and Load
|
||||
test.RunClassFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing the field of a local struct works
|
||||
test.RunStructLclFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing the field of a local struct works, using pinning and Load
|
||||
test.RunStructLclFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing an instance member of a struct works
|
||||
test.RunStructFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing an instance member of a struct works, using pinning and Load
|
||||
test.RunStructFldScenario_Load();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Validates we throw on unsupported hardware
|
||||
test.RunUnsupportedScenario();
|
||||
}
|
||||
|
||||
if (!test.Succeeded)
|
||||
{
|
||||
throw new Exception("One or more scenarios did not complete as expected.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed unsafe class SimpleBinaryOpTest__VectorTableLookup_Vector64_SByte
|
||||
{
|
||||
private struct DataTable
|
||||
{
|
||||
private byte[] inArray1;
|
||||
private byte[] inArray2;
|
||||
private byte[] outArray;
|
||||
|
||||
private GCHandle inHandle1;
|
||||
private GCHandle inHandle2;
|
||||
private GCHandle outHandle;
|
||||
|
||||
private ulong alignment;
|
||||
|
||||
public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment)
|
||||
{
|
||||
int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
|
||||
int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<SByte>();
|
||||
int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<SByte>();
|
||||
if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
|
||||
{
|
||||
throw new ArgumentException("Invalid value of alignment");
|
||||
}
|
||||
|
||||
this.inArray1 = new byte[alignment * 2];
|
||||
this.inArray2 = new byte[alignment * 2];
|
||||
this.outArray = new byte[alignment * 2];
|
||||
|
||||
this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
|
||||
this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
|
||||
this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
|
||||
|
||||
this.alignment = (ulong)alignment;
|
||||
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<SByte, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<SByte, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
|
||||
}
|
||||
|
||||
public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
inHandle1.Free();
|
||||
inHandle2.Free();
|
||||
outHandle.Free();
|
||||
}
|
||||
|
||||
private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
|
||||
{
|
||||
return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
|
||||
}
|
||||
}
|
||||
|
||||
private struct TestStruct
|
||||
{
|
||||
public Vector128<SByte> _fld1;
|
||||
public Vector64<SByte> _fld2;
|
||||
|
||||
public static TestStruct Create()
|
||||
{
|
||||
var testStruct = new TestStruct();
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref testStruct._fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (SByte)(TestLibrary.Generator.GetSByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
|
||||
|
||||
return testStruct;
|
||||
}
|
||||
|
||||
public void RunStructFldScenario(SimpleBinaryOpTest__VectorTableLookup_Vector64_SByte testClass)
|
||||
{
|
||||
var result = AdvSimd.VectorTableLookup(_fld1, _fld2);
|
||||
|
||||
Unsafe.Write(testClass._dataTable.outArrayPtr, result);
|
||||
testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario_Load(SimpleBinaryOpTest__VectorTableLookup_Vector64_SByte testClass)
|
||||
{
|
||||
fixed (Vector128<SByte>* pFld1 = &_fld1)
|
||||
fixed (Vector64<SByte>* pFld2 = &_fld2)
|
||||
{
|
||||
var result = AdvSimd.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((SByte*)(pFld1)),
|
||||
AdvSimd.LoadVector64((SByte*)(pFld2))
|
||||
);
|
||||
|
||||
Unsafe.Write(testClass._dataTable.outArrayPtr, result);
|
||||
testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly int LargestVectorSize = 16;
|
||||
|
||||
private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
|
||||
private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
|
||||
private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
|
||||
|
||||
private static SByte[] _data1 = new SByte[Op1ElementCount];
|
||||
private static SByte[] _data2 = new SByte[Op2ElementCount];
|
||||
|
||||
private static Vector128<SByte> _clsVar1;
|
||||
private static Vector64<SByte> _clsVar2;
|
||||
|
||||
private Vector128<SByte> _fld1;
|
||||
private Vector64<SByte> _fld2;
|
||||
|
||||
private DataTable _dataTable;
|
||||
|
||||
static SimpleBinaryOpTest__VectorTableLookup_Vector64_SByte()
|
||||
{
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (SByte)(TestLibrary.Generator.GetSByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
|
||||
}
|
||||
|
||||
public SimpleBinaryOpTest__VectorTableLookup_Vector64_SByte()
|
||||
{
|
||||
Succeeded = true;
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (SByte)(TestLibrary.Generator.GetSByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (SByte)(TestLibrary.Generator.GetSByte() % 20); }
|
||||
_dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize);
|
||||
}
|
||||
|
||||
public bool IsSupported => AdvSimd.IsSupported;
|
||||
|
||||
public bool Succeeded { get; set; }
|
||||
|
||||
public void RunBasicScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
|
||||
|
||||
var result = AdvSimd.VectorTableLookup(
|
||||
Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
|
||||
Unsafe.Read<Vector64<SByte>>(_dataTable.inArray2Ptr)
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunBasicScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
|
||||
|
||||
var result = AdvSimd.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
|
||||
AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunReflectionScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
|
||||
|
||||
var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.VectorTableLookup), new Type[] { typeof(Vector128<SByte>), typeof(Vector64<SByte>) })
|
||||
.Invoke(null, new object[] {
|
||||
Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
|
||||
Unsafe.Read<Vector64<SByte>>(_dataTable.inArray2Ptr)
|
||||
});
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, (Vector64<SByte>)(result));
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunReflectionScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
|
||||
|
||||
var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.VectorTableLookup), new Type[] { typeof(Vector128<SByte>), typeof(Vector64<SByte>) })
|
||||
.Invoke(null, new object[] {
|
||||
AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
|
||||
AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr))
|
||||
});
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, (Vector64<SByte>)(result));
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClsVarScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
|
||||
|
||||
var result = AdvSimd.VectorTableLookup(
|
||||
_clsVar1,
|
||||
_clsVar2
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClsVarScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
|
||||
|
||||
fixed (Vector128<SByte>* pClsVar1 = &_clsVar1)
|
||||
fixed (Vector64<SByte>* pClsVar2 = &_clsVar2)
|
||||
{
|
||||
var result = AdvSimd.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((SByte*)(pClsVar1)),
|
||||
AdvSimd.LoadVector64((SByte*)(pClsVar2))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunLclVarScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
|
||||
|
||||
var op1 = Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr);
|
||||
var op2 = Unsafe.Read<Vector64<SByte>>(_dataTable.inArray2Ptr);
|
||||
var result = AdvSimd.VectorTableLookup(op1, op2);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(op1, op2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunLclVarScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
|
||||
|
||||
var op1 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr));
|
||||
var op2 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr));
|
||||
var result = AdvSimd.VectorTableLookup(op1, op2);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(op1, op2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassLclFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
|
||||
|
||||
var test = new SimpleBinaryOpTest__VectorTableLookup_Vector64_SByte();
|
||||
var result = AdvSimd.VectorTableLookup(test._fld1, test._fld2);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassLclFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
|
||||
|
||||
var test = new SimpleBinaryOpTest__VectorTableLookup_Vector64_SByte();
|
||||
|
||||
fixed (Vector128<SByte>* pFld1 = &test._fld1)
|
||||
fixed (Vector64<SByte>* pFld2 = &test._fld2)
|
||||
{
|
||||
var result = AdvSimd.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((SByte*)(pFld1)),
|
||||
AdvSimd.LoadVector64((SByte*)(pFld2))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunClassFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
|
||||
|
||||
var result = AdvSimd.VectorTableLookup(_fld1, _fld2);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
|
||||
|
||||
fixed (Vector128<SByte>* pFld1 = &_fld1)
|
||||
fixed (Vector64<SByte>* pFld2 = &_fld2)
|
||||
{
|
||||
var result = AdvSimd.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((SByte*)(pFld1)),
|
||||
AdvSimd.LoadVector64((SByte*)(pFld2))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunStructLclFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
var result = AdvSimd.VectorTableLookup(test._fld1, test._fld2);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructLclFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
var result = AdvSimd.VectorTableLookup(
|
||||
AdvSimd.LoadVector128((SByte*)(&test._fld1)),
|
||||
AdvSimd.LoadVector64((SByte*)(&test._fld2))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
test.RunStructFldScenario(this);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
test.RunStructFldScenario_Load(this);
|
||||
}
|
||||
|
||||
public void RunUnsupportedScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
|
||||
|
||||
bool succeeded = false;
|
||||
|
||||
try
|
||||
{
|
||||
RunBasicScenario_UnsafeRead();
|
||||
}
|
||||
catch (PlatformNotSupportedException)
|
||||
{
|
||||
succeeded = true;
|
||||
}
|
||||
|
||||
if (!succeeded)
|
||||
{
|
||||
Succeeded = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateResult(Vector128<SByte> op1, Vector64<SByte> op2, void* result, [CallerMemberName] string method = "")
|
||||
{
|
||||
SByte[] inArray1 = new SByte[Op1ElementCount];
|
||||
SByte[] inArray2 = new SByte[Op2ElementCount];
|
||||
SByte[] outArray = new SByte[RetElementCount];
|
||||
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), op2);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
|
||||
|
||||
ValidateResult(inArray1, inArray2, outArray, method);
|
||||
}
|
||||
|
||||
private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
|
||||
{
|
||||
SByte[] inArray1 = new SByte[Op1ElementCount];
|
||||
SByte[] inArray2 = new SByte[Op2ElementCount];
|
||||
SByte[] outArray = new SByte[RetElementCount];
|
||||
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<SByte>>());
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
|
||||
|
||||
ValidateResult(inArray1, inArray2, outArray, method);
|
||||
}
|
||||
|
||||
private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "")
|
||||
{
|
||||
bool succeeded = true;
|
||||
|
||||
if (Helpers.TableVectorLookup(0, right, left) != result[0])
|
||||
{
|
||||
succeeded = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 1; i < RetElementCount; i++)
|
||||
{
|
||||
if (Helpers.TableVectorLookup(i, right, left) != result[i])
|
||||
{
|
||||
succeeded = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!succeeded)
|
||||
{
|
||||
TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.VectorTableLookup)}<SByte>(Vector128<SByte>, Vector64<SByte>): {method} failed:");
|
||||
TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
|
||||
TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
|
||||
TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
|
||||
TestLibrary.TestFramework.LogInformation(string.Empty);
|
||||
|
||||
Succeeded = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,571 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
/******************************************************************************
|
||||
* This file is auto-generated from a template file by the GenerateTests.csx *
|
||||
* script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make *
|
||||
* changes, please update the corresponding template and run according to the *
|
||||
* directions listed in the file. *
|
||||
******************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.Arm;
|
||||
|
||||
namespace JIT.HardwareIntrinsics.Arm
|
||||
{
|
||||
public static partial class Program
|
||||
{
|
||||
private static void VectorTableLookupExtension_Vector64_Byte()
|
||||
{
|
||||
var test = new SimpleTernaryOpTest__VectorTableLookupExtension_Vector64_Byte();
|
||||
|
||||
if (test.IsSupported)
|
||||
{
|
||||
// Validates basic functionality works, using Unsafe.Read
|
||||
test.RunBasicScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates basic functionality works, using Load
|
||||
test.RunBasicScenario_Load();
|
||||
}
|
||||
|
||||
// Validates calling via reflection works, using Unsafe.Read
|
||||
test.RunReflectionScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates calling via reflection works, using Load
|
||||
test.RunReflectionScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing a static member works
|
||||
test.RunClsVarScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing a static member works, using pinning and Load
|
||||
test.RunClsVarScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing a local works, using Unsafe.Read
|
||||
test.RunLclVarScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing a local works, using Load
|
||||
test.RunLclVarScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing the field of a local class works
|
||||
test.RunClassLclFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing the field of a local class works, using pinning and Load
|
||||
test.RunClassLclFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing an instance member of a class works
|
||||
test.RunClassFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing an instance member of a class works, using pinning and Load
|
||||
test.RunClassFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing the field of a local struct works
|
||||
test.RunStructLclFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing the field of a local struct works, using pinning and Load
|
||||
test.RunStructLclFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing an instance member of a struct works
|
||||
test.RunStructFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing an instance member of a struct works, using pinning and Load
|
||||
test.RunStructFldScenario_Load();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Validates we throw on unsupported hardware
|
||||
test.RunUnsupportedScenario();
|
||||
}
|
||||
|
||||
if (!test.Succeeded)
|
||||
{
|
||||
throw new Exception("One or more scenarios did not complete as expected.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed unsafe class SimpleTernaryOpTest__VectorTableLookupExtension_Vector64_Byte
|
||||
{
|
||||
private struct DataTable
|
||||
{
|
||||
private byte[] inArray1;
|
||||
private byte[] inArray2;
|
||||
private byte[] inArray3;
|
||||
private byte[] outArray;
|
||||
|
||||
private GCHandle inHandle1;
|
||||
private GCHandle inHandle2;
|
||||
private GCHandle inHandle3;
|
||||
private GCHandle outHandle;
|
||||
|
||||
private ulong alignment;
|
||||
|
||||
public DataTable(Byte[] inArray1, Byte[] inArray2, Byte[] inArray3, Byte[] outArray, int alignment)
|
||||
{
|
||||
int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
|
||||
int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Byte>();
|
||||
int sizeOfinArray3 = inArray3.Length * Unsafe.SizeOf<Byte>();
|
||||
int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Byte>();
|
||||
if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfinArray3 || (alignment * 2) < sizeOfoutArray)
|
||||
{
|
||||
throw new ArgumentException("Invalid value of alignment");
|
||||
}
|
||||
|
||||
this.inArray1 = new byte[alignment * 2];
|
||||
this.inArray2 = new byte[alignment * 2];
|
||||
this.inArray3 = new byte[alignment * 2];
|
||||
this.outArray = new byte[alignment * 2];
|
||||
|
||||
this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
|
||||
this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
|
||||
this.inHandle3 = GCHandle.Alloc(this.inArray3, GCHandleType.Pinned);
|
||||
this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
|
||||
|
||||
this.alignment = (ulong)alignment;
|
||||
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Byte, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Byte, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray3Ptr), ref Unsafe.As<Byte, byte>(ref inArray3[0]), (uint)sizeOfinArray3);
|
||||
}
|
||||
|
||||
public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
public void* inArray3Ptr => Align((byte*)(inHandle3.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
inHandle1.Free();
|
||||
inHandle2.Free();
|
||||
inHandle3.Free();
|
||||
outHandle.Free();
|
||||
}
|
||||
|
||||
private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
|
||||
{
|
||||
return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
|
||||
}
|
||||
}
|
||||
|
||||
private struct TestStruct
|
||||
{
|
||||
public Vector64<Byte> _fld1;
|
||||
public Vector128<Byte> _fld2;
|
||||
public Vector64<Byte> _fld3;
|
||||
|
||||
public static TestStruct Create()
|
||||
{
|
||||
var testStruct = new TestStruct();
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref testStruct._fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = (Byte)(TestLibrary.Generator.GetByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref testStruct._fld3), ref Unsafe.As<Byte, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
|
||||
|
||||
return testStruct;
|
||||
}
|
||||
|
||||
public void RunStructFldScenario(SimpleTernaryOpTest__VectorTableLookupExtension_Vector64_Byte testClass)
|
||||
{
|
||||
var result = AdvSimd.VectorTableLookupExtension(_fld1, _fld2, _fld3);
|
||||
|
||||
Unsafe.Write(testClass._dataTable.outArrayPtr, result);
|
||||
testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario_Load(SimpleTernaryOpTest__VectorTableLookupExtension_Vector64_Byte testClass)
|
||||
{
|
||||
fixed (Vector64<Byte>* pFld1 = &_fld1)
|
||||
fixed (Vector128<Byte>* pFld2 = &_fld2)
|
||||
fixed (Vector64<Byte>* pFld3 = &_fld3)
|
||||
{
|
||||
var result = AdvSimd.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector64((Byte*)(pFld1)),
|
||||
AdvSimd.LoadVector128((Byte*)(pFld2)),
|
||||
AdvSimd.LoadVector64((Byte*)(pFld3))
|
||||
);
|
||||
|
||||
Unsafe.Write(testClass._dataTable.outArrayPtr, result);
|
||||
testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly int LargestVectorSize = 16;
|
||||
|
||||
private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
|
||||
private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
|
||||
private static readonly int Op3ElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
|
||||
private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
|
||||
|
||||
private static Byte[] _data1 = new Byte[Op1ElementCount];
|
||||
private static Byte[] _data2 = new Byte[Op2ElementCount];
|
||||
private static Byte[] _data3 = new Byte[Op3ElementCount];
|
||||
|
||||
private static Vector64<Byte> _clsVar1;
|
||||
private static Vector128<Byte> _clsVar2;
|
||||
private static Vector64<Byte> _clsVar3;
|
||||
|
||||
private Vector64<Byte> _fld1;
|
||||
private Vector128<Byte> _fld2;
|
||||
private Vector64<Byte> _fld3;
|
||||
|
||||
private DataTable _dataTable;
|
||||
|
||||
static SimpleTernaryOpTest__VectorTableLookupExtension_Vector64_Byte()
|
||||
{
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _clsVar1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = (Byte)(TestLibrary.Generator.GetByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _clsVar3), ref Unsafe.As<Byte, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
|
||||
}
|
||||
|
||||
public SimpleTernaryOpTest__VectorTableLookupExtension_Vector64_Byte()
|
||||
{
|
||||
Succeeded = true;
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = (Byte)(TestLibrary.Generator.GetByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _fld3), ref Unsafe.As<Byte, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
|
||||
for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = (Byte)(TestLibrary.Generator.GetByte() % 20); }
|
||||
_dataTable = new DataTable(_data1, _data2, _data3, new Byte[RetElementCount], LargestVectorSize);
|
||||
}
|
||||
|
||||
public bool IsSupported => AdvSimd.IsSupported;
|
||||
|
||||
public bool Succeeded { get; set; }
|
||||
|
||||
public void RunBasicScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
|
||||
|
||||
var result = AdvSimd.VectorTableLookupExtension(
|
||||
Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr),
|
||||
Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr),
|
||||
Unsafe.Read<Vector64<Byte>>(_dataTable.inArray3Ptr)
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunBasicScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
|
||||
|
||||
var result = AdvSimd.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)),
|
||||
AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr)),
|
||||
AdvSimd.LoadVector64((Byte*)(_dataTable.inArray3Ptr))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunReflectionScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
|
||||
|
||||
var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.VectorTableLookupExtension), new Type[] { typeof(Vector64<Byte>), typeof(Vector128<Byte>), typeof(Vector64<Byte>) })
|
||||
.Invoke(null, new object[] {
|
||||
Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr),
|
||||
Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr),
|
||||
Unsafe.Read<Vector64<Byte>>(_dataTable.inArray3Ptr)
|
||||
});
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Byte>)(result));
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunReflectionScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
|
||||
|
||||
var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.VectorTableLookupExtension), new Type[] { typeof(Vector64<Byte>), typeof(Vector128<Byte>), typeof(Vector64<Byte>) })
|
||||
.Invoke(null, new object[] {
|
||||
AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)),
|
||||
AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr)),
|
||||
AdvSimd.LoadVector64((Byte*)(_dataTable.inArray3Ptr))
|
||||
});
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Byte>)(result));
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClsVarScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
|
||||
|
||||
var result = AdvSimd.VectorTableLookupExtension(
|
||||
_clsVar1,
|
||||
_clsVar2,
|
||||
_clsVar3
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_clsVar1, _clsVar2, _clsVar3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClsVarScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
|
||||
|
||||
fixed (Vector64<Byte>* pClsVar1 = &_clsVar1)
|
||||
fixed (Vector128<Byte>* pClsVar2 = &_clsVar2)
|
||||
fixed (Vector64<Byte>* pClsVar3 = &_clsVar3)
|
||||
{
|
||||
var result = AdvSimd.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector64((Byte*)(pClsVar1)),
|
||||
AdvSimd.LoadVector128((Byte*)(pClsVar2)),
|
||||
AdvSimd.LoadVector64((Byte*)(pClsVar3))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_clsVar1, _clsVar2, _clsVar3, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunLclVarScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
|
||||
|
||||
var op1 = Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr);
|
||||
var op2 = Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr);
|
||||
var op3 = Unsafe.Read<Vector64<Byte>>(_dataTable.inArray3Ptr);
|
||||
var result = AdvSimd.VectorTableLookupExtension(op1, op2, op3);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(op1, op2, op3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunLclVarScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
|
||||
|
||||
var op1 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr));
|
||||
var op2 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr));
|
||||
var op3 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray3Ptr));
|
||||
var result = AdvSimd.VectorTableLookupExtension(op1, op2, op3);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(op1, op2, op3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassLclFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
|
||||
|
||||
var test = new SimpleTernaryOpTest__VectorTableLookupExtension_Vector64_Byte();
|
||||
var result = AdvSimd.VectorTableLookupExtension(test._fld1, test._fld2, test._fld3);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassLclFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
|
||||
|
||||
var test = new SimpleTernaryOpTest__VectorTableLookupExtension_Vector64_Byte();
|
||||
|
||||
fixed (Vector64<Byte>* pFld1 = &test._fld1)
|
||||
fixed (Vector128<Byte>* pFld2 = &test._fld2)
|
||||
fixed (Vector64<Byte>* pFld3 = &test._fld3)
|
||||
{
|
||||
var result = AdvSimd.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector64((Byte*)(pFld1)),
|
||||
AdvSimd.LoadVector128((Byte*)(pFld2)),
|
||||
AdvSimd.LoadVector64((Byte*)(pFld3))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunClassFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
|
||||
|
||||
var result = AdvSimd.VectorTableLookupExtension(_fld1, _fld2, _fld3);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
|
||||
|
||||
fixed (Vector64<Byte>* pFld1 = &_fld1)
|
||||
fixed (Vector128<Byte>* pFld2 = &_fld2)
|
||||
fixed (Vector64<Byte>* pFld3 = &_fld3)
|
||||
{
|
||||
var result = AdvSimd.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector64((Byte*)(pFld1)),
|
||||
AdvSimd.LoadVector128((Byte*)(pFld2)),
|
||||
AdvSimd.LoadVector64((Byte*)(pFld3))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunStructLclFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
var result = AdvSimd.VectorTableLookupExtension(test._fld1, test._fld2, test._fld3);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructLclFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
var result = AdvSimd.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector64((Byte*)(&test._fld1)),
|
||||
AdvSimd.LoadVector128((Byte*)(&test._fld2)),
|
||||
AdvSimd.LoadVector64((Byte*)(&test._fld3))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
test.RunStructFldScenario(this);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
test.RunStructFldScenario_Load(this);
|
||||
}
|
||||
|
||||
public void RunUnsupportedScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
|
||||
|
||||
bool succeeded = false;
|
||||
|
||||
try
|
||||
{
|
||||
RunBasicScenario_UnsafeRead();
|
||||
}
|
||||
catch (PlatformNotSupportedException)
|
||||
{
|
||||
succeeded = true;
|
||||
}
|
||||
|
||||
if (!succeeded)
|
||||
{
|
||||
Succeeded = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateResult(Vector64<Byte> op1, Vector128<Byte> op2, Vector64<Byte> op3, void* result, [CallerMemberName] string method = "")
|
||||
{
|
||||
Byte[] inArray1 = new Byte[Op1ElementCount];
|
||||
Byte[] inArray2 = new Byte[Op2ElementCount];
|
||||
Byte[] inArray3 = new Byte[Op3ElementCount];
|
||||
Byte[] outArray = new Byte[RetElementCount];
|
||||
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), op2);
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray3[0]), op3);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
|
||||
|
||||
ValidateResult(inArray1, inArray2, inArray3, outArray, method);
|
||||
}
|
||||
|
||||
private void ValidateResult(void* op1, void* op2, void* op3, void* result, [CallerMemberName] string method = "")
|
||||
{
|
||||
Byte[] inArray1 = new Byte[Op1ElementCount];
|
||||
Byte[] inArray2 = new Byte[Op2ElementCount];
|
||||
Byte[] inArray3 = new Byte[Op3ElementCount];
|
||||
Byte[] outArray = new Byte[RetElementCount];
|
||||
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Byte>>());
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Byte>>());
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray3[0]), ref Unsafe.AsRef<byte>(op3), (uint)Unsafe.SizeOf<Vector64<Byte>>());
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
|
||||
|
||||
ValidateResult(inArray1, inArray2, inArray3, outArray, method);
|
||||
}
|
||||
|
||||
private void ValidateResult(Byte[] firstOp, Byte[] secondOp, Byte[] thirdOp, Byte[] result, [CallerMemberName] string method = "")
|
||||
{
|
||||
bool succeeded = true;
|
||||
|
||||
for (var i = 0; i < RetElementCount; i++)
|
||||
{
|
||||
if (Helpers.TableVectorExtension(i, firstOp, thirdOp, secondOp) != result[i])
|
||||
{
|
||||
succeeded = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!succeeded)
|
||||
{
|
||||
TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.VectorTableLookupExtension)}<Byte>(Vector64<Byte>, Vector128<Byte>, Vector64<Byte>): {method} failed:");
|
||||
TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})");
|
||||
TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})");
|
||||
TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})");
|
||||
TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
|
||||
TestLibrary.TestFramework.LogInformation(string.Empty);
|
||||
|
||||
Succeeded = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,571 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
/******************************************************************************
|
||||
* This file is auto-generated from a template file by the GenerateTests.csx *
|
||||
* script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make *
|
||||
* changes, please update the corresponding template and run according to the *
|
||||
* directions listed in the file. *
|
||||
******************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.Arm;
|
||||
|
||||
namespace JIT.HardwareIntrinsics.Arm
|
||||
{
|
||||
public static partial class Program
|
||||
{
|
||||
private static void VectorTableLookupExtension_Vector64_SByte()
|
||||
{
|
||||
var test = new SimpleTernaryOpTest__VectorTableLookupExtension_Vector64_SByte();
|
||||
|
||||
if (test.IsSupported)
|
||||
{
|
||||
// Validates basic functionality works, using Unsafe.Read
|
||||
test.RunBasicScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates basic functionality works, using Load
|
||||
test.RunBasicScenario_Load();
|
||||
}
|
||||
|
||||
// Validates calling via reflection works, using Unsafe.Read
|
||||
test.RunReflectionScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates calling via reflection works, using Load
|
||||
test.RunReflectionScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing a static member works
|
||||
test.RunClsVarScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing a static member works, using pinning and Load
|
||||
test.RunClsVarScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing a local works, using Unsafe.Read
|
||||
test.RunLclVarScenario_UnsafeRead();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing a local works, using Load
|
||||
test.RunLclVarScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing the field of a local class works
|
||||
test.RunClassLclFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing the field of a local class works, using pinning and Load
|
||||
test.RunClassLclFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing an instance member of a class works
|
||||
test.RunClassFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing an instance member of a class works, using pinning and Load
|
||||
test.RunClassFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing the field of a local struct works
|
||||
test.RunStructLclFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing the field of a local struct works, using pinning and Load
|
||||
test.RunStructLclFldScenario_Load();
|
||||
}
|
||||
|
||||
// Validates passing an instance member of a struct works
|
||||
test.RunStructFldScenario();
|
||||
|
||||
if (AdvSimd.IsSupported)
|
||||
{
|
||||
// Validates passing an instance member of a struct works, using pinning and Load
|
||||
test.RunStructFldScenario_Load();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Validates we throw on unsupported hardware
|
||||
test.RunUnsupportedScenario();
|
||||
}
|
||||
|
||||
if (!test.Succeeded)
|
||||
{
|
||||
throw new Exception("One or more scenarios did not complete as expected.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed unsafe class SimpleTernaryOpTest__VectorTableLookupExtension_Vector64_SByte
|
||||
{
|
||||
private struct DataTable
|
||||
{
|
||||
private byte[] inArray1;
|
||||
private byte[] inArray2;
|
||||
private byte[] inArray3;
|
||||
private byte[] outArray;
|
||||
|
||||
private GCHandle inHandle1;
|
||||
private GCHandle inHandle2;
|
||||
private GCHandle inHandle3;
|
||||
private GCHandle outHandle;
|
||||
|
||||
private ulong alignment;
|
||||
|
||||
public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] inArray3, SByte[] outArray, int alignment)
|
||||
{
|
||||
int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
|
||||
int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<SByte>();
|
||||
int sizeOfinArray3 = inArray3.Length * Unsafe.SizeOf<SByte>();
|
||||
int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<SByte>();
|
||||
if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfinArray3 || (alignment * 2) < sizeOfoutArray)
|
||||
{
|
||||
throw new ArgumentException("Invalid value of alignment");
|
||||
}
|
||||
|
||||
this.inArray1 = new byte[alignment * 2];
|
||||
this.inArray2 = new byte[alignment * 2];
|
||||
this.inArray3 = new byte[alignment * 2];
|
||||
this.outArray = new byte[alignment * 2];
|
||||
|
||||
this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
|
||||
this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
|
||||
this.inHandle3 = GCHandle.Alloc(this.inArray3, GCHandleType.Pinned);
|
||||
this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
|
||||
|
||||
this.alignment = (ulong)alignment;
|
||||
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<SByte, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<SByte, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray3Ptr), ref Unsafe.As<SByte, byte>(ref inArray3[0]), (uint)sizeOfinArray3);
|
||||
}
|
||||
|
||||
public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
public void* inArray3Ptr => Align((byte*)(inHandle3.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
inHandle1.Free();
|
||||
inHandle2.Free();
|
||||
inHandle3.Free();
|
||||
outHandle.Free();
|
||||
}
|
||||
|
||||
private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
|
||||
{
|
||||
return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
|
||||
}
|
||||
}
|
||||
|
||||
private struct TestStruct
|
||||
{
|
||||
public Vector64<SByte> _fld1;
|
||||
public Vector128<SByte> _fld2;
|
||||
public Vector64<SByte> _fld3;
|
||||
|
||||
public static TestStruct Create()
|
||||
{
|
||||
var testStruct = new TestStruct();
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref testStruct._fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = (SByte)(TestLibrary.Generator.GetSByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref testStruct._fld3), ref Unsafe.As<SByte, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
|
||||
|
||||
return testStruct;
|
||||
}
|
||||
|
||||
public void RunStructFldScenario(SimpleTernaryOpTest__VectorTableLookupExtension_Vector64_SByte testClass)
|
||||
{
|
||||
var result = AdvSimd.VectorTableLookupExtension(_fld1, _fld2, _fld3);
|
||||
|
||||
Unsafe.Write(testClass._dataTable.outArrayPtr, result);
|
||||
testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario_Load(SimpleTernaryOpTest__VectorTableLookupExtension_Vector64_SByte testClass)
|
||||
{
|
||||
fixed (Vector64<SByte>* pFld1 = &_fld1)
|
||||
fixed (Vector128<SByte>* pFld2 = &_fld2)
|
||||
fixed (Vector64<SByte>* pFld3 = &_fld3)
|
||||
{
|
||||
var result = AdvSimd.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector64((SByte*)(pFld1)),
|
||||
AdvSimd.LoadVector128((SByte*)(pFld2)),
|
||||
AdvSimd.LoadVector64((SByte*)(pFld3))
|
||||
);
|
||||
|
||||
Unsafe.Write(testClass._dataTable.outArrayPtr, result);
|
||||
testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly int LargestVectorSize = 16;
|
||||
|
||||
private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
|
||||
private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
|
||||
private static readonly int Op3ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
|
||||
private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
|
||||
|
||||
private static SByte[] _data1 = new SByte[Op1ElementCount];
|
||||
private static SByte[] _data2 = new SByte[Op2ElementCount];
|
||||
private static SByte[] _data3 = new SByte[Op3ElementCount];
|
||||
|
||||
private static Vector64<SByte> _clsVar1;
|
||||
private static Vector128<SByte> _clsVar2;
|
||||
private static Vector64<SByte> _clsVar3;
|
||||
|
||||
private Vector64<SByte> _fld1;
|
||||
private Vector128<SByte> _fld2;
|
||||
private Vector64<SByte> _fld3;
|
||||
|
||||
private DataTable _dataTable;
|
||||
|
||||
static SimpleTernaryOpTest__VectorTableLookupExtension_Vector64_SByte()
|
||||
{
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _clsVar1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = (SByte)(TestLibrary.Generator.GetSByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _clsVar3), ref Unsafe.As<SByte, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
|
||||
}
|
||||
|
||||
public SimpleTernaryOpTest__VectorTableLookupExtension_Vector64_SByte()
|
||||
{
|
||||
Succeeded = true;
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = (SByte)(TestLibrary.Generator.GetSByte() % 20); }
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _fld3), ref Unsafe.As<SByte, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
|
||||
|
||||
for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
|
||||
for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
|
||||
for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = (SByte)(TestLibrary.Generator.GetSByte() % 20); }
|
||||
_dataTable = new DataTable(_data1, _data2, _data3, new SByte[RetElementCount], LargestVectorSize);
|
||||
}
|
||||
|
||||
public bool IsSupported => AdvSimd.IsSupported;
|
||||
|
||||
public bool Succeeded { get; set; }
|
||||
|
||||
public void RunBasicScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
|
||||
|
||||
var result = AdvSimd.VectorTableLookupExtension(
|
||||
Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr),
|
||||
Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr),
|
||||
Unsafe.Read<Vector64<SByte>>(_dataTable.inArray3Ptr)
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunBasicScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
|
||||
|
||||
var result = AdvSimd.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)),
|
||||
AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)),
|
||||
AdvSimd.LoadVector64((SByte*)(_dataTable.inArray3Ptr))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunReflectionScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
|
||||
|
||||
var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.VectorTableLookupExtension), new Type[] { typeof(Vector64<SByte>), typeof(Vector128<SByte>), typeof(Vector64<SByte>) })
|
||||
.Invoke(null, new object[] {
|
||||
Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr),
|
||||
Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr),
|
||||
Unsafe.Read<Vector64<SByte>>(_dataTable.inArray3Ptr)
|
||||
});
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, (Vector64<SByte>)(result));
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunReflectionScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
|
||||
|
||||
var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.VectorTableLookupExtension), new Type[] { typeof(Vector64<SByte>), typeof(Vector128<SByte>), typeof(Vector64<SByte>) })
|
||||
.Invoke(null, new object[] {
|
||||
AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)),
|
||||
AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)),
|
||||
AdvSimd.LoadVector64((SByte*)(_dataTable.inArray3Ptr))
|
||||
});
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, (Vector64<SByte>)(result));
|
||||
ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClsVarScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
|
||||
|
||||
var result = AdvSimd.VectorTableLookupExtension(
|
||||
_clsVar1,
|
||||
_clsVar2,
|
||||
_clsVar3
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_clsVar1, _clsVar2, _clsVar3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClsVarScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
|
||||
|
||||
fixed (Vector64<SByte>* pClsVar1 = &_clsVar1)
|
||||
fixed (Vector128<SByte>* pClsVar2 = &_clsVar2)
|
||||
fixed (Vector64<SByte>* pClsVar3 = &_clsVar3)
|
||||
{
|
||||
var result = AdvSimd.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector64((SByte*)(pClsVar1)),
|
||||
AdvSimd.LoadVector128((SByte*)(pClsVar2)),
|
||||
AdvSimd.LoadVector64((SByte*)(pClsVar3))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_clsVar1, _clsVar2, _clsVar3, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunLclVarScenario_UnsafeRead()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
|
||||
|
||||
var op1 = Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr);
|
||||
var op2 = Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr);
|
||||
var op3 = Unsafe.Read<Vector64<SByte>>(_dataTable.inArray3Ptr);
|
||||
var result = AdvSimd.VectorTableLookupExtension(op1, op2, op3);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(op1, op2, op3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunLclVarScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
|
||||
|
||||
var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr));
|
||||
var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr));
|
||||
var op3 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray3Ptr));
|
||||
var result = AdvSimd.VectorTableLookupExtension(op1, op2, op3);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(op1, op2, op3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassLclFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
|
||||
|
||||
var test = new SimpleTernaryOpTest__VectorTableLookupExtension_Vector64_SByte();
|
||||
var result = AdvSimd.VectorTableLookupExtension(test._fld1, test._fld2, test._fld3);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassLclFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
|
||||
|
||||
var test = new SimpleTernaryOpTest__VectorTableLookupExtension_Vector64_SByte();
|
||||
|
||||
fixed (Vector64<SByte>* pFld1 = &test._fld1)
|
||||
fixed (Vector128<SByte>* pFld2 = &test._fld2)
|
||||
fixed (Vector64<SByte>* pFld3 = &test._fld3)
|
||||
{
|
||||
var result = AdvSimd.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector64((SByte*)(pFld1)),
|
||||
AdvSimd.LoadVector128((SByte*)(pFld2)),
|
||||
AdvSimd.LoadVector64((SByte*)(pFld3))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunClassFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
|
||||
|
||||
var result = AdvSimd.VectorTableLookupExtension(_fld1, _fld2, _fld3);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunClassFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
|
||||
|
||||
fixed (Vector64<SByte>* pFld1 = &_fld1)
|
||||
fixed (Vector128<SByte>* pFld2 = &_fld2)
|
||||
fixed (Vector64<SByte>* pFld3 = &_fld3)
|
||||
{
|
||||
var result = AdvSimd.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector64((SByte*)(pFld1)),
|
||||
AdvSimd.LoadVector128((SByte*)(pFld2)),
|
||||
AdvSimd.LoadVector64((SByte*)(pFld3))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RunStructLclFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
var result = AdvSimd.VectorTableLookupExtension(test._fld1, test._fld2, test._fld3);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructLclFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
var result = AdvSimd.VectorTableLookupExtension(
|
||||
AdvSimd.LoadVector64((SByte*)(&test._fld1)),
|
||||
AdvSimd.LoadVector128((SByte*)(&test._fld2)),
|
||||
AdvSimd.LoadVector64((SByte*)(&test._fld3))
|
||||
);
|
||||
|
||||
Unsafe.Write(_dataTable.outArrayPtr, result);
|
||||
ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
test.RunStructFldScenario(this);
|
||||
}
|
||||
|
||||
public void RunStructFldScenario_Load()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
|
||||
|
||||
var test = TestStruct.Create();
|
||||
test.RunStructFldScenario_Load(this);
|
||||
}
|
||||
|
||||
public void RunUnsupportedScenario()
|
||||
{
|
||||
TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
|
||||
|
||||
bool succeeded = false;
|
||||
|
||||
try
|
||||
{
|
||||
RunBasicScenario_UnsafeRead();
|
||||
}
|
||||
catch (PlatformNotSupportedException)
|
||||
{
|
||||
succeeded = true;
|
||||
}
|
||||
|
||||
if (!succeeded)
|
||||
{
|
||||
Succeeded = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateResult(Vector64<SByte> op1, Vector128<SByte> op2, Vector64<SByte> op3, void* result, [CallerMemberName] string method = "")
|
||||
{
|
||||
SByte[] inArray1 = new SByte[Op1ElementCount];
|
||||
SByte[] inArray2 = new SByte[Op2ElementCount];
|
||||
SByte[] inArray3 = new SByte[Op3ElementCount];
|
||||
SByte[] outArray = new SByte[RetElementCount];
|
||||
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), op2);
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray3[0]), op3);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
|
||||
|
||||
ValidateResult(inArray1, inArray2, inArray3, outArray, method);
|
||||
}
|
||||
|
||||
private void ValidateResult(void* op1, void* op2, void* op3, void* result, [CallerMemberName] string method = "")
|
||||
{
|
||||
SByte[] inArray1 = new SByte[Op1ElementCount];
|
||||
SByte[] inArray2 = new SByte[Op2ElementCount];
|
||||
SByte[] inArray3 = new SByte[Op3ElementCount];
|
||||
SByte[] outArray = new SByte[RetElementCount];
|
||||
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<SByte>>());
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<SByte>>());
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray3[0]), ref Unsafe.AsRef<byte>(op3), (uint)Unsafe.SizeOf<Vector64<SByte>>());
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
|
||||
|
||||
ValidateResult(inArray1, inArray2, inArray3, outArray, method);
|
||||
}
|
||||
|
||||
private void ValidateResult(SByte[] firstOp, SByte[] secondOp, SByte[] thirdOp, SByte[] result, [CallerMemberName] string method = "")
|
||||
{
|
||||
bool succeeded = true;
|
||||
|
||||
for (var i = 0; i < RetElementCount; i++)
|
||||
{
|
||||
if (Helpers.TableVectorExtension(i, firstOp, thirdOp, secondOp) != result[i])
|
||||
{
|
||||
succeeded = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!succeeded)
|
||||
{
|
||||
TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.VectorTableLookupExtension)}<SByte>(Vector64<SByte>, Vector128<SByte>, Vector64<SByte>): {method} failed:");
|
||||
TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})");
|
||||
TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})");
|
||||
TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})");
|
||||
TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
|
||||
TestLibrary.TestFramework.LogInformation(string.Empty);
|
||||
|
||||
Succeeded = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -654,6 +654,10 @@ private static readonly (string templateFileName, Dictionary<string, string> tem
|
|||
("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "SubtractScalar_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.Subtract(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}),
|
||||
("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "SubtractScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.Subtract(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}),
|
||||
("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "SubtractScalar_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.Subtract(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}),
|
||||
("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "VectorTableLookup_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookup", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "(Byte)(TestLibrary.Generator.GetByte() % 20)", ["ValidateFirstResult"] = "Helpers.TableVectorLookup(0, right, left) != result[0]", ["ValidateRemainingResults"] = "Helpers.TableVectorLookup(i, right, left) != result[i]"}),
|
||||
("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "VectorTableLookup_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookup", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "(SByte)(TestLibrary.Generator.GetSByte() % 20)", ["ValidateFirstResult"] = "Helpers.TableVectorLookup(0, right, left) != result[0]", ["ValidateRemainingResults"] = "Helpers.TableVectorLookup(i, right, left) != result[i]"}),
|
||||
("VecTernOpTest.template", new Dictionary<string, string> { ["TestName"] = "VectorTableLookupExtension_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookupExtension", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "(Byte)(TestLibrary.Generator.GetByte() % 20)", ["ValidateIterResult"] = "Helpers.TableVectorExtension(i, firstOp, thirdOp, secondOp) != result[i]"}),
|
||||
("VecTernOpTest.template", new Dictionary<string, string> { ["TestName"] = "VectorTableLookupExtension_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookupExtension", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "(SByte)(TestLibrary.Generator.GetSByte() % 20)", ["ValidateIterResult"] = "Helpers.TableVectorExtension(i, firstOp, thirdOp, secondOp) != result[i]"}),
|
||||
("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Xor_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}),
|
||||
("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Xor_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Xor(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}),
|
||||
("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Xor_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}),
|
||||
|
@ -894,6 +898,10 @@ private static readonly (string templateFileName, Dictionary<string, string> tem
|
|||
("VecPairBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "TransposeOdd_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}),
|
||||
("VecPairBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "TransposeOdd_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}),
|
||||
("VecPairBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "TransposeOdd_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}),
|
||||
("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "VectorTableLookup_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookup", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "(Byte)(TestLibrary.Generator.GetByte() % 20)", ["ValidateFirstResult"] = "Helpers.TableVectorLookup(0, right, left) != result[0]", ["ValidateRemainingResults"] = "Helpers.TableVectorLookup(i, right, left) != result[i]"}),
|
||||
("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "VectorTableLookup_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookup", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "(SByte)(TestLibrary.Generator.GetSByte() % 20)", ["ValidateFirstResult"] = "Helpers.TableVectorLookup(0, right, left) != result[0]", ["ValidateRemainingResults"] = "Helpers.TableVectorLookup(i, right, left) != result[i]"}),
|
||||
("VecTernOpTest.template", new Dictionary<string, string> { ["TestName"] = "VectorTableLookupExtension_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookupExtension", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "(Byte)(TestLibrary.Generator.GetByte() % 20)", ["ValidateIterResult"] = "Helpers.TableVectorExtension(i, firstOp, thirdOp, secondOp) != result[i]"}),
|
||||
("VecTernOpTest.template", new Dictionary<string, string> { ["TestName"] = "VectorTableLookupExtension_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookupExtension", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "(SByte)(TestLibrary.Generator.GetSByte() % 20)", ["ValidateIterResult"] = "Helpers.TableVectorExtension(i, firstOp, thirdOp, secondOp) != result[i]"}),
|
||||
("VecPairBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "UnzipEven_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}),
|
||||
("VecPairBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "UnzipEven_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}),
|
||||
("VecPairBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "UnzipEven_Vector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}),
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
// "%DevEnvDir%\TextTransform.exe" .\Helpers.tt
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace JIT.HardwareIntrinsics.Arm
|
||||
{
|
||||
|
@ -2391,5 +2392,41 @@ namespace JIT.HardwareIntrinsics.Arm
|
|||
|
||||
public static double Insert(double[] op1, int op2, double op3, int i) => (op2 != i) ? op1[i] : op3;
|
||||
|
||||
public static sbyte TableVectorExtension(int i, sbyte[] defaultValues, sbyte[] indices, params sbyte[][] table)
|
||||
{
|
||||
sbyte[] fullTable = table.SelectMany(x => x).ToArray();
|
||||
int index = indices[i];
|
||||
|
||||
if (index < 0 || index >= fullTable.Length)
|
||||
return defaultValues[i];
|
||||
|
||||
return fullTable[index];
|
||||
}
|
||||
|
||||
public static sbyte TableVectorLookup(int i, sbyte[] indices, params sbyte[][] table)
|
||||
{
|
||||
sbyte[] zeros = new sbyte[indices.Length];
|
||||
Array.Fill<sbyte>(zeros, 0, 0, indices.Length);
|
||||
|
||||
return TableVectorExtension(i, zeros, indices, table);
|
||||
}
|
||||
public static byte TableVectorExtension(int i, byte[] defaultValues, byte[] indices, params byte[][] table)
|
||||
{
|
||||
byte[] fullTable = table.SelectMany(x => x).ToArray();
|
||||
int index = indices[i];
|
||||
|
||||
if (index < 0 || index >= fullTable.Length)
|
||||
return defaultValues[i];
|
||||
|
||||
return fullTable[index];
|
||||
}
|
||||
|
||||
public static byte TableVectorLookup(int i, byte[] indices, params byte[][] table)
|
||||
{
|
||||
byte[] zeros = new byte[indices.Length];
|
||||
Array.Fill<byte>(zeros, 0, 0, indices.Length);
|
||||
|
||||
return TableVectorExtension(i, zeros, indices, table);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
// "%DevEnvDir%\TextTransform.exe" .\Helpers.tt
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace JIT.HardwareIntrinsics.Arm
|
||||
{
|
||||
|
@ -605,6 +606,30 @@ namespace JIT.HardwareIntrinsics.Arm
|
|||
|
||||
public static <#= typeName #> Insert(<#= typeName #>[] op1, int op2, <#= typeName #> op3, int i) => (op2 != i) ? op1[i] : op3;
|
||||
|
||||
<#
|
||||
}
|
||||
|
||||
foreach (string typeName in new string[] { "sbyte", "byte" })
|
||||
{
|
||||
#>
|
||||
public static <#= typeName #> TableVectorExtension(int i, <#= typeName #>[] defaultValues, <#= typeName #>[] indices, params <#= typeName #>[][] table)
|
||||
{
|
||||
<#= typeName #>[] fullTable = table.SelectMany(x => x).ToArray();
|
||||
int index = indices[i];
|
||||
|
||||
if (index < 0 || index >= fullTable.Length)
|
||||
return defaultValues[i];
|
||||
|
||||
return fullTable[index];
|
||||
}
|
||||
|
||||
public static <#= typeName #> TableVectorLookup(int i, <#= typeName #>[] indices, params <#= typeName #>[][] table)
|
||||
{
|
||||
<#= typeName #>[] zeros = new <#= typeName #>[indices.Length];
|
||||
Array.Fill<<#= typeName #>>(zeros, 0, 0, indices.Length);
|
||||
|
||||
return TableVectorExtension(i, zeros, indices, table);
|
||||
}
|
||||
<#
|
||||
}
|
||||
#>
|
||||
|
|
|
@ -1584,6 +1584,29 @@ namespace System.Runtime.Intrinsics.Arm
|
|||
/// </summary>
|
||||
public static Vector128<ulong> UnzipOdd(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
|
||||
|
||||
/// <summary>
|
||||
/// uint8x16_t vqvtbl1q_u8(uint8x16_t t, uint8x16_t idx)
|
||||
/// A64: TBL Vd.16B, {Vn.16B}, Vm.16B
|
||||
/// </summary>
|
||||
public static Vector128<byte> VectorTableLookup(Vector128<byte> table, Vector128<byte> byteIndexes) { throw new PlatformNotSupportedException(); }
|
||||
|
||||
/// <summary>
|
||||
/// int8x16_t vqvtbl1q_s8(int8x16_t t, uint8x16_t idx)
|
||||
/// A64: TBL Vd.16B, {Vn.16B}, Vm.16B
|
||||
/// </summary>
|
||||
public static Vector128<sbyte> VectorTableLookup(Vector128<sbyte> table, Vector128<sbyte> byteIndexes) { throw new PlatformNotSupportedException(); }
|
||||
/// <summary>
|
||||
/// uint8x16_t vqvtbx1q_u8(uint8x16_t r, int8x16_t t, uint8x16_t idx)
|
||||
/// A64: TBX Vd.16B, {Vn.16B}, Vm.16B
|
||||
/// </summary>
|
||||
public static Vector128<byte> VectorTableLookupExtension(Vector128<byte> defaultValues, Vector128<byte> table, Vector128<byte> byteIndexes) { throw new PlatformNotSupportedException(); }
|
||||
|
||||
/// <summary>
|
||||
/// int8x16_t vqvtbx1q_s8(int8x16_t r, int8x16_t t, uint8x16_t idx)
|
||||
/// A64: TBX Vd.16B, {Vn.16B}, Vm.16B
|
||||
/// </summary>
|
||||
public static Vector128<sbyte> VectorTableLookupExtension(Vector128<sbyte> defaultValues, Vector128<sbyte> table, Vector128<sbyte> byteIndexes) { throw new PlatformNotSupportedException(); }
|
||||
|
||||
/// <summary>
|
||||
/// uint8x8_t vzip2_u8(uint8x8_t a, uint8x8_t b)
|
||||
/// A64: ZIP2 Vd.8B, Vn.8B, Vm.8B
|
||||
|
@ -5681,6 +5704,34 @@ namespace System.Runtime.Intrinsics.Arm
|
|||
/// </summary>
|
||||
public static Vector64<float> SubtractScalar(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
|
||||
|
||||
/// <summary>
|
||||
/// uint8x8_t vqvtbl1_u8(uint8x16_t t, uint8x8_t idx)
|
||||
/// A32: VTBL Dd, {Dn, Dn+1}, Dm
|
||||
/// A64: TBL Vd.8B, {Vn.16B}, Vm.8B
|
||||
/// </summary>
|
||||
public static Vector64<byte> VectorTableLookup(Vector128<byte> table, Vector64<byte> byteIndexes) { throw new PlatformNotSupportedException(); }
|
||||
|
||||
/// <summary>
|
||||
/// int8x8_t vqvtbl1_s8(int8x16_t t, uint8x8_t idx)
|
||||
/// A32: VTBL Dd, {Dn, Dn+1}, Dm
|
||||
/// A64: TBL Vd.8B, {Vn.16B}, Vm.8B
|
||||
/// </summary>
|
||||
public static Vector64<sbyte> VectorTableLookup(Vector128<sbyte> table, Vector64<sbyte> byteIndexes) { throw new PlatformNotSupportedException(); }
|
||||
|
||||
/// <summary>
|
||||
/// uint8x8_t vqvtbx1_u8(uint8x8_t r, uint8x16_t t, uint8x8_t idx)
|
||||
/// A32: VTBX Dd, {Dn, Dn+1}, Dm
|
||||
/// A64: TBX Vd.8B, {Vn.16B}, Vm.8B
|
||||
/// </summary>
|
||||
public static Vector64<byte> VectorTableLookupExtension(Vector64<byte> defaultValues, Vector128<byte> table, Vector64<byte> byteIndexes) { throw new PlatformNotSupportedException(); }
|
||||
|
||||
/// <summary>
|
||||
/// int8x8_t vqvtbx1_s8(int8x8_t r, int8x16_t t, uint8x8_t idx)
|
||||
/// A32: VTBX Dd, {Dn, Dn+1}, Dm
|
||||
/// A64: TBX Vd.8B, {Vn.16B}, Vm.8B
|
||||
/// </summary>
|
||||
public static Vector64<sbyte> VectorTableLookupExtension(Vector64<sbyte> defaultValues, Vector128<sbyte> table, Vector64<sbyte> byteIndexes) { throw new PlatformNotSupportedException(); }
|
||||
|
||||
/// <summary>
|
||||
/// uint64x1_t vsub_u64 (uint64x1_t a, uint64x1_t b)
|
||||
/// A32: VSUB.I64 Dd, Dn, Dm
|
||||
|
|
|
@ -1586,6 +1586,30 @@ namespace System.Runtime.Intrinsics.Arm
|
|||
/// </summary>
|
||||
public static Vector128<ulong> UnzipOdd(Vector128<ulong> left, Vector128<ulong> right) => UnzipOdd(left, right);
|
||||
|
||||
/// <summary>
|
||||
/// uint8x16_t vqvtbl1q_u8(uint8x16_t t, uint8x16_t idx)
|
||||
/// A64: TBL Vd.16B, {Vn.16B}, Vm.16B
|
||||
/// </summary>
|
||||
public static Vector128<byte> VectorTableLookup(Vector128<byte> table, Vector128<byte> byteIndexes) => VectorTableLookup(table, byteIndexes);
|
||||
|
||||
/// <summary>
|
||||
/// int8x16_t vqvtbl1q_s8(int8x16_t t, uint8x16_t idx)
|
||||
/// A64: TBL Vd.16B, {Vn.16B}, Vm.16B
|
||||
/// </summary>
|
||||
public static Vector128<sbyte> VectorTableLookup(Vector128<sbyte> table, Vector128<sbyte> byteIndexes) => VectorTableLookup(table, byteIndexes);
|
||||
|
||||
/// <summary>
|
||||
/// uint8x16_t vqvtbx1q_u8(uint8x16_t r, int8x16_t t, uint8x16_t idx)
|
||||
/// A64: TBX Vd.16B, {Vn.16B}, Vm.16B
|
||||
/// </summary>
|
||||
public static Vector128<byte> VectorTableLookupExtension(Vector128<byte> defaultValues, Vector128<byte> table, Vector128<byte> byteIndexes) => VectorTableLookupExtension(defaultValues, table, byteIndexes);
|
||||
|
||||
/// <summary>
|
||||
/// int8x16_t vqvtbx1q_s8(int8x16_t r, int8x16_t t, uint8x16_t idx)
|
||||
/// A64: TBX Vd.16B, {Vn.16B}, Vm.16B
|
||||
/// </summary>
|
||||
public static Vector128<sbyte> VectorTableLookupExtension(Vector128<sbyte> defaultValues, Vector128<sbyte> table, Vector128<sbyte> byteIndexes) => VectorTableLookupExtension(defaultValues, table, byteIndexes);
|
||||
|
||||
/// <summary>
|
||||
/// uint8x8_t vzip2_u8(uint8x8_t a, uint8x8_t b)
|
||||
/// A64: ZIP2 Vd.8B, Vn.8B, Vm.8B
|
||||
|
@ -5690,6 +5714,34 @@ namespace System.Runtime.Intrinsics.Arm
|
|||
/// </summary>
|
||||
public static Vector64<ulong> SubtractScalar(Vector64<ulong> left, Vector64<ulong> right) => SubtractScalar(left, right);
|
||||
|
||||
/// <summary>
|
||||
/// uint8x8_t vqvtbl1_u8(uint8x16_t t, uint8x8_t idx)
|
||||
/// A32: VTBL Dd, {Dn, Dn+1}, Dm
|
||||
/// A64: TBL Vd.8B, {Vn.16B}, Vm.8B
|
||||
/// </summary>
|
||||
public static Vector64<byte> VectorTableLookup(Vector128<byte> table, Vector64<byte> byteIndexes) => VectorTableLookup(table, byteIndexes);
|
||||
|
||||
/// <summary>
|
||||
/// int8x8_t vqvtbl1_s8(int8x16_t t, uint8x8_t idx)
|
||||
/// A32: VTBL Dd, {Dn, Dn+1}, Dm
|
||||
/// A64: TBL Vd.8B, {Vn.16B}, Vm.8B
|
||||
/// </summary>
|
||||
public static Vector64<sbyte> VectorTableLookup(Vector128<sbyte> table, Vector64<sbyte> byteIndexes) => VectorTableLookup(table, byteIndexes);
|
||||
|
||||
/// <summary>
|
||||
/// uint8x8_t vqvtbx1_u8(uint8x8_t r, uint8x16_t t, uint8x8_t idx)
|
||||
/// A32: VTBX Dd, {Dn, Dn+1}, Dm
|
||||
/// A64: TBX Vd.8B, {Vn.16B}, Vm.8B
|
||||
/// </summary>
|
||||
public static Vector64<byte> VectorTableLookupExtension(Vector64<byte> defaultValues, Vector128<byte> table, Vector64<byte> byteIndexes) => VectorTableLookupExtension(defaultValues, table, byteIndexes);
|
||||
|
||||
/// <summary>
|
||||
/// int8x8_t vqvtbx1_s8(int8x8_t r, int8x16_t t, uint8x8_t idx)
|
||||
/// A32: VTBX Dd, {Dn, Dn+1}, Dm
|
||||
/// A64: TBX Vd.8B, {Vn.16B}, Vm.8B
|
||||
/// </summary>
|
||||
public static Vector64<sbyte> VectorTableLookupExtension(Vector64<sbyte> defaultValues, Vector128<sbyte> table, Vector64<sbyte> byteIndexes) => VectorTableLookupExtension(defaultValues, table, byteIndexes);
|
||||
|
||||
/// <summary>
|
||||
/// uint8x8_t veor_u8 (uint8x8_t a, uint8x8_t b)
|
||||
/// A32: VEOR Dd, Dn, Dm
|
||||
|
|
|
@ -564,6 +564,10 @@ namespace System.Runtime.Intrinsics.Arm
|
|||
public static System.Runtime.Intrinsics.Vector64<long> SubtractScalar(System.Runtime.Intrinsics.Vector64<long> left, System.Runtime.Intrinsics.Vector64<long> right) { throw null; }
|
||||
public static System.Runtime.Intrinsics.Vector64<float> SubtractScalar(System.Runtime.Intrinsics.Vector64<float> left, System.Runtime.Intrinsics.Vector64<float> right) { throw null; }
|
||||
public static System.Runtime.Intrinsics.Vector64<ulong> SubtractScalar(System.Runtime.Intrinsics.Vector64<ulong> left, System.Runtime.Intrinsics.Vector64<ulong> right) { throw null; }
|
||||
public static System.Runtime.Intrinsics.Vector64<byte> VectorTableLookup(System.Runtime.Intrinsics.Vector128<byte> table, System.Runtime.Intrinsics.Vector64<byte> byteIndexes) { throw null; }
|
||||
public static System.Runtime.Intrinsics.Vector64<sbyte> VectorTableLookup(System.Runtime.Intrinsics.Vector128<sbyte> table, System.Runtime.Intrinsics.Vector64<sbyte> byteIndexes) { throw null; }
|
||||
public static System.Runtime.Intrinsics.Vector64<byte> VectorTableLookupExtension(System.Runtime.Intrinsics.Vector64<byte> defaultValues, System.Runtime.Intrinsics.Vector128<byte> table, System.Runtime.Intrinsics.Vector64<byte> byteIndexes) { throw null; }
|
||||
public static System.Runtime.Intrinsics.Vector64<sbyte> VectorTableLookupExtension(System.Runtime.Intrinsics.Vector64<sbyte> defaultValues, System.Runtime.Intrinsics.Vector128<sbyte> table, System.Runtime.Intrinsics.Vector64<sbyte> byteIndexes) { throw null; }
|
||||
public static System.Runtime.Intrinsics.Vector128<byte> Xor(System.Runtime.Intrinsics.Vector128<byte> left, System.Runtime.Intrinsics.Vector128<byte> right) { throw null; }
|
||||
public static System.Runtime.Intrinsics.Vector128<double> Xor(System.Runtime.Intrinsics.Vector128<double> left, System.Runtime.Intrinsics.Vector128<double> right) { throw null; }
|
||||
public static System.Runtime.Intrinsics.Vector128<short> Xor(System.Runtime.Intrinsics.Vector128<short> left, System.Runtime.Intrinsics.Vector128<short> right) { throw null; }
|
||||
|
@ -838,6 +842,10 @@ namespace System.Runtime.Intrinsics.Arm
|
|||
public static System.Runtime.Intrinsics.Vector64<float> UnzipOdd(System.Runtime.Intrinsics.Vector64<float> left, System.Runtime.Intrinsics.Vector64<float> right) { throw null; }
|
||||
public static System.Runtime.Intrinsics.Vector64<ushort> UnzipOdd(System.Runtime.Intrinsics.Vector64<ushort> left, System.Runtime.Intrinsics.Vector64<ushort> right) { throw null; }
|
||||
public static System.Runtime.Intrinsics.Vector64<uint> UnzipOdd(System.Runtime.Intrinsics.Vector64<uint> left, System.Runtime.Intrinsics.Vector64<uint> right) { throw null; }
|
||||
public static System.Runtime.Intrinsics.Vector128<byte> VectorTableLookup(System.Runtime.Intrinsics.Vector128<byte> table, System.Runtime.Intrinsics.Vector128<byte> byteIndexes) { throw null; }
|
||||
public static System.Runtime.Intrinsics.Vector128<sbyte> VectorTableLookup(System.Runtime.Intrinsics.Vector128<sbyte> table, System.Runtime.Intrinsics.Vector128<sbyte> byteIndexes) { throw null; }
|
||||
public static System.Runtime.Intrinsics.Vector128<byte> VectorTableLookupExtension(System.Runtime.Intrinsics.Vector128<byte> defaultValues, System.Runtime.Intrinsics.Vector128<byte> table, System.Runtime.Intrinsics.Vector128<byte> byteIndexes) { throw null; }
|
||||
public static System.Runtime.Intrinsics.Vector128<sbyte> VectorTableLookupExtension(System.Runtime.Intrinsics.Vector128<sbyte> defaultValues, System.Runtime.Intrinsics.Vector128<sbyte> table, System.Runtime.Intrinsics.Vector128<sbyte> byteIndexes) { throw null; }
|
||||
public static System.Runtime.Intrinsics.Vector128<byte> ZipHigh(System.Runtime.Intrinsics.Vector128<byte> left, System.Runtime.Intrinsics.Vector128<byte> right) { throw null; }
|
||||
public static System.Runtime.Intrinsics.Vector128<double> ZipHigh(System.Runtime.Intrinsics.Vector128<double> left, System.Runtime.Intrinsics.Vector128<double> right) { throw null; }
|
||||
public static System.Runtime.Intrinsics.Vector128<short> ZipHigh(System.Runtime.Intrinsics.Vector128<short> left, System.Runtime.Intrinsics.Vector128<short> right) { throw null; }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue