Skip to content

Commit

Permalink
Add Arm64 encoding for group SVE_DF_2A and SVE_DK_3A (#97774)
Browse files Browse the repository at this point in the history
  • Loading branch information
SwapnilGaikwad authored Jan 31, 2024
1 parent bfa39b3 commit 5167715
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 13 deletions.
16 changes: 16 additions & 0 deletions src/coreclr/jit/codegenarm64test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4914,13 +4914,29 @@ void CodeGen::genArm64EmitterUnitTestsSve()
SVE_PATTERN_ALL); // PTRUES <Pd>.<T>{, <pattern>}
theEmitter->emitIns_R_PATTERN(INS_sve_ptrues, EA_SCALABLE, REG_P15,
INS_OPTS_SCALABLE_D); // PTRUES <Pd>.<T>{, <pattern>}
// IF_SVE_DF_2A
theEmitter->emitIns_R_R(INS_sve_pnext, EA_SCALABLE, REG_P0, REG_P15,
INS_OPTS_SCALABLE_B); // PNEXT <Pdn>.<T>, <Pv>, <Pdn>.<T>

// IF_SVE_DG_2A
theEmitter->emitIns_R_R(INS_sve_rdffr, EA_SCALABLE, REG_P10, REG_P15,
INS_OPTS_SCALABLE_B); // RDFFR <Pd>.B, <Pg>/Z
theEmitter->emitIns_R_R(INS_sve_rdffrs, EA_SCALABLE, REG_P7, REG_P14,
INS_OPTS_SCALABLE_B); // RDFFRS <Pd>.B, <Pg>/Z

// IF_SVE_DH_1A
theEmitter->emitIns_R(INS_sve_rdffr, EA_SCALABLE, REG_P8); // RDFFR <Pd>.B

// IF_SVE_DJ_1A
theEmitter->emitIns_R(INS_sve_pfalse, EA_SCALABLE, REG_P13); // PFALSE <Pd>.B

// IF_SVE_DI_2A
theEmitter->emitIns_R_R(INS_sve_ptest, EA_SCALABLE, REG_P2, REG_P14, INS_OPTS_SCALABLE_B); // PTEST <Pg>, <Pn>.B

// IF_SVE_DK_3A
theEmitter->emitIns_R_R_R(INS_sve_cntp, EA_8BYTE, REG_R29, REG_P0, REG_P15,
INS_OPTS_SCALABLE_D); // CNTP <Xd>, <Pg>, <Pn>.<T>

// IF_SVE_EP_3A
theEmitter->emitIns_R_R_R(INS_sve_shadd, EA_SCALABLE, REG_V15, REG_P0, REG_V10,
INS_OPTS_SCALABLE_B); // SHADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
Expand Down
166 changes: 153 additions & 13 deletions src/coreclr/jit/emitarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1212,6 +1212,31 @@ void emitter::emitInsSanityCheck(instrDesc* id)
assert(insOptsScalableStandard(id->idInsOpt())); // xx
break;

case IF_SVE_DF_2A: // ........xx...... .......VVVV.DDDD -- SVE predicate next active
case IF_SVE_DI_2A: // ................ ..gggg.NNNN..... -- SVE predicate test
elemsize = id->idOpSize();
assert(isScalableVectorSize(elemsize));
assert(insOptsScalableStandard(id->idInsOpt()));
assert(isPredicateRegister(id->idReg1())); // DDDD
assert(isPredicateRegister(id->idReg2())); // gggg
break;

case IF_SVE_DH_1A: // ................ ............DDDD -- SVE predicate read from FFR (unpredicated)
case IF_SVE_DJ_1A: // ................ ............DDDD -- SVE predicate zero
elemsize = id->idOpSize();
assert(isScalableVectorSize(elemsize));
assert(id->idInsOpt() == INS_OPTS_SCALABLE_B);
assert(isPredicateRegister(id->idReg1())); // DDDD
break;

case IF_SVE_DK_3A: // ........xx...... ..gggg.NNNNddddd -- SVE predicate count
assert(id->idOpSize() == EA_8BYTE);
assert(insOptsScalableStandard(id->idInsOpt()));
assert(isGeneralRegister(id->idReg1())); // ddddd
assert(isPredicateRegister(id->idReg2())); // gggg
assert(isPredicateRegister(id->idReg3())); // NNNN
break;

case IF_SVE_GE_4A: // ........xx.mmmmm ...gggnnnnn.DDDD -- SVE2 character match
elemsize = id->idOpSize();
assert(isScalableVectorSize(elemsize));
Expand Down Expand Up @@ -6176,34 +6201,41 @@ void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg, insOpts o
case INS_br:
case INS_ret:
assert(isGeneralRegister(reg));
id->idReg1(reg);
fmt = IF_BR_1A;
break;

case INS_dczva:
assert(isGeneralRegister(reg));
assert(attr == EA_8BYTE);
id->idReg1(reg);
fmt = IF_SR_1A;
break;

case INS_mrs_tpid0:
id->idReg1(reg);
fmt = IF_SR_1A;
break;

case INS_sve_aesmc:
case INS_sve_aesimc:
id->idInsOpt(INS_OPTS_SCALABLE_B);
id->idReg1(reg);
assert(isVectorRegister(reg)); // ddddd
assert(isScalableVectorSize(attr));
fmt = IF_SVE_GL_1A;
break;

case INS_sve_rdffr:
id->idInsOpt(INS_OPTS_SCALABLE_B);
assert(isPredicateRegister(reg)); // DDDD
fmt = IF_SVE_DH_1A;
break;

case INS_sve_pfalse:
id->idInsOpt(INS_OPTS_SCALABLE_B);
assert(isPredicateRegister(reg)); // DDDD
fmt = IF_SVE_DJ_1A;
break;

case INS_sve_wrffr:
id->idInsOpt(INS_OPTS_SCALABLE_B);
id->idReg1(reg);
assert(isPredicateRegister(reg)); // NNNN
fmt = IF_SVE_DR_1A;
break;
Expand All @@ -6212,7 +6244,6 @@ void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg, insOpts o
assert(insOptsScalableStandard(opt));
assert(isHighPredicateRegister(reg)); // DDD
assert(isValidVectorElemsize(optGetSveElemsize(opt))); // xx
id->idReg1(reg);
id->idInsOpt(opt);
fmt = IF_SVE_DZ_1A;
break;
Expand All @@ -6225,6 +6256,7 @@ void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg, insOpts o

id->idIns(ins);
id->idInsFmt(fmt);
id->idReg1(reg);

dispIns(id);
appendToCurIG(id);
Expand Down Expand Up @@ -7539,6 +7571,14 @@ void emitter::emitIns_R_R(instruction ins,
fmt = IF_SVE_DD_2A;
break;

case INS_sve_pnext:
assert(insOptsScalableStandard(opt));
assert(isPredicateRegister(reg1)); // DDDD
assert(isPredicateRegister(reg2)); // VVVV
assert(isValidVectorElemsize(optGetSveElemsize(opt))); // xx
fmt = IF_SVE_DF_2A;
break;

case INS_sve_rdffr:
case INS_sve_rdffrs:
assert(opt == INS_OPTS_SCALABLE_B);
Expand All @@ -7547,6 +7587,13 @@ void emitter::emitIns_R_R(instruction ins,
fmt = IF_SVE_DG_2A;
break;

case INS_sve_ptest:
assert(opt == INS_OPTS_SCALABLE_B);
assert(isPredicateRegister(reg1)); // gggg
assert(isPredicateRegister(reg2)); // NNNN
fmt = IF_SVE_DI_2A;
break;

case INS_sve_cntp:
assert(insOptsScalableStandard(opt));
assert(insScalableOptsWithVectorLength(sopt)); // l
Expand Down Expand Up @@ -9694,6 +9741,15 @@ void emitter::emitIns_R_R_R(instruction ins,
fmt = IF_SVE_DC_3A;
break;

case INS_sve_cntp:
assert(size == EA_8BYTE);
assert(isGeneralRegister(reg1)); // ddddd
assert(isPredicateRegister(reg2)); // gggg
assert(isPredicateRegister(reg3)); // NNNN
assert(isValidVectorElemsize(optGetSveElemsize(opt))); // xx
fmt = IF_SVE_DK_3A;
break;

case INS_sve_shadd:
case INS_sve_shsub:
case INS_sve_shsubr:
Expand Down Expand Up @@ -15086,6 +15142,8 @@ void emitter::emitIns_Call(EmitCallType callType,
case IF_SVE_CF_2D:
case IF_SVE_CI_3A:
case IF_SVE_DE_1A:
case IF_SVE_DH_1A:
case IF_SVE_DJ_1A:
case IF_SVE_DM_2A:
case IF_SVE_DN_2A:
case IF_SVE_DO_2A:
Expand All @@ -15094,7 +15152,6 @@ void emitter::emitIns_Call(EmitCallType callType,
case IF_SVE_DT_3A:
case IF_SVE_DU_3A:
case IF_SVE_CK_2A:
case IF_SVE_DI_2A:
return PREDICATE_SIZED;

case IF_SVE_DB_3A:
Expand Down Expand Up @@ -15153,7 +15210,6 @@ void emitter::emitIns_Call(EmitCallType callType,
case IF_SVE_CS_3A:
case IF_SVE_CV_3A:
case IF_SVE_CV_3B:
case IF_SVE_DK_3A:
case IF_SVE_DW_2A: // <PNn>[<imm>]
case IF_SVE_DW_2B: // <PNn>[<imm>]
case IF_SVE_JC_4A:
Expand All @@ -15168,16 +15224,11 @@ void emitter::emitIns_Call(EmitCallType callType,
case IF_SVE_AJ_3A:
case IF_SVE_AL_3A:
case IF_SVE_CL_3A:
case IF_SVE_DF_2A:
case IF_SVE_GS_3A:
case IF_SVE_HJ_3A:
case IF_SVE_IY_4A:
return PREDICATE_NONE;

case IF_SVE_DD_2A:
assert((regpos >= 1) && (regpos <= 3));
return ((regpos == 2) ? PREDICATE_NONE : PREDICATE_SIZED);

case IF_SVE_CX_4A:
case IF_SVE_CX_4A_A:
case IF_SVE_CY_3A:
Expand All @@ -15198,9 +15249,21 @@ void emitter::emitIns_Call(EmitCallType callType,
assert((regpos >= 1) && (regpos <= 3));
return (regpos == 2 ? PREDICATE_MERGE : PREDICATE_SIZED);

case IF_SVE_DD_2A:
case IF_SVE_DF_2A:
assert((regpos >= 1) && (regpos <= 3));
return ((regpos == 2) ? PREDICATE_NONE : PREDICATE_SIZED);

case IF_SVE_DG_2A:
return (regpos == 2 ? PREDICATE_ZERO : PREDICATE_SIZED);

case IF_SVE_DI_2A:
return (regpos == 1 ? PREDICATE_NONE : PREDICATE_SIZED);

case IF_SVE_DK_3A:
assert((regpos == 2) || (regpos == 3));
return ((regpos == 2) ? PREDICATE_NONE : PREDICATE_SIZED);

default:
break;
}
Expand Down Expand Up @@ -18054,6 +18117,37 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
dst += emitOutput_Instr(dst, code);
break;

case IF_SVE_DF_2A: // ........xx...... .......VVVV.DDDD -- SVE predicate next active
code = emitInsCodeSve(ins, fmt);
code |= insEncodeReg_P_3_to_0(id->idReg1()); // DDDD
code |= insEncodeReg_P_8_to_5(id->idReg2()); // VVVV
code |= insEncodeElemsize(optGetSveElemsize(id->idInsOpt())); // xx
dst += emitOutput_Instr(dst, code);
break;

case IF_SVE_DH_1A: // ................ ............DDDD -- SVE predicate read from FFR (unpredicated)
case IF_SVE_DJ_1A: // ................ ............DDDD -- SVE predicate zero
code = emitInsCodeSve(ins, fmt);
code |= insEncodeReg_P_3_to_0(id->idReg1()); // DDDD
dst += emitOutput_Instr(dst, code);
break;

case IF_SVE_DI_2A: // ................ ..gggg.NNNN..... -- SVE predicate test
code = emitInsCodeSve(ins, fmt);
code |= insEncodeReg_P_13_to_10(id->idReg1()); // gggg
code |= insEncodeReg_P_8_to_5(id->idReg2()); // NNNN
dst += emitOutput_Instr(dst, code);
break;

case IF_SVE_DK_3A: // ........xx...... ..gggg.NNNNddddd -- SVE predicate count
code = emitInsCodeSve(ins, fmt);
code |= insEncodeReg_R_4_to_0(id->idReg1()); // ddddd
code |= insEncodeReg_P_13_to_10(id->idReg2()); // gggg
code |= insEncodeReg_P_8_to_5(id->idReg3()); // NNNN
code |= insEncodeElemsize(optGetSveElemsize(id->idInsOpt())); // xx
dst += emitOutput_Instr(dst, code);
break;

case IF_SVE_GA_2A: // ............iiii ......nnnn.ddddd -- SME2 multi-vec shift narrow
imm = emitGetInsSC(id);
assert(id->idInsOpt() == INS_OPTS_SCALABLE_H);
Expand Down Expand Up @@ -21112,12 +21206,33 @@ void emitter::emitDispInsHelp(
break;
}

// <Pdn>.<T>, <Pv>, <Pdn>.<T>
case IF_SVE_DF_2A: // ........xx...... .......VVVV.DDDD -- SVE predicate next active
emitDispPredicateReg(id->idReg1(), insGetPredicateType(fmt, 1), id->idInsOpt(), true); // DDDD
emitDispPredicateReg(id->idReg2(), insGetPredicateType(fmt, 2), id->idInsOpt(), true); // VVVV
emitDispPredicateReg(id->idReg1(), insGetPredicateType(fmt, 3), id->idInsOpt(), false); // DDDD
break;

// <Pd>.B, <Pg>/Z
case IF_SVE_DG_2A: // ................ .......gggg.DDDD -- SVE predicate read from FFR (predicated)
case IF_SVE_DI_2A: // ................ ..gggg.NNNN..... -- SVE predicate test
emitDispPredicateReg(id->idReg1(), insGetPredicateType(fmt, 1), id->idInsOpt(), true); // DDDD
emitDispPredicateReg(id->idReg2(), insGetPredicateType(fmt, 2), id->idInsOpt(), false); // gggg
break;

// <Pd>.B
case IF_SVE_DH_1A: // ................ ............DDDD -- SVE predicate read from FFR (unpredicated)
case IF_SVE_DJ_1A: // ................ ............DDDD -- SVE predicate zero
emitDispPredicateReg(id->idReg1(), insGetPredicateType(fmt), id->idInsOpt(), false); // DDDD
break;

// <Xd>, <Pg>, <Pn>.<T>
case IF_SVE_DK_3A: // ........xx...... ..gggg.NNNNddddd -- SVE predicate count
emitDispReg(id->idReg1(), size, true); // ddddd
emitDispPredicateReg(id->idReg2(), insGetPredicateType(fmt, 2), id->idInsOpt(), true); // gggg
emitDispPredicateReg(id->idReg3(), insGetPredicateType(fmt, 3), id->idInsOpt(), false); // NNNN
break;

// <Zda>.<T>, <Pg>/M, <Zn>.<Tb>
case IF_SVE_EQ_3A: // ........xx...... ...gggnnnnnddddd -- SVE2 integer pairwise add and accumulate long
emitDispSveReg(id->idReg1(), id->idInsOpt(), true); // ddddd
Expand Down Expand Up @@ -23967,6 +24082,11 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins
}
break;

case IF_SVE_DF_2A: // ........xx...... .......VVVV.DDDD -- SVE predicate next active
result.insLatency = PERFSCORE_LATENCY_3C;
result.insThroughput = PERFSCORE_THROUGHPUT_2C;
break;

case IF_SVE_DG_2A: // ................ .......gggg.DDDD -- SVE predicate read from FFR (predicated)
switch (ins)
{
Expand All @@ -23987,6 +24107,26 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins
}
break;

case IF_SVE_DH_1A: // ................ ............DDDD -- SVE predicate read from FFR (unpredicated)
result.insLatency = PERFSCORE_LATENCY_3C;
result.insThroughput = PERFSCORE_THROUGHPUT_1C;
break;

case IF_SVE_DJ_1A: // ................ ............DDDD -- SVE predicate zero
result.insLatency = PERFSCORE_LATENCY_2C;
result.insThroughput = PERFSCORE_THROUGHPUT_2C;
break;

case IF_SVE_DI_2A: // ................ ..gggg.NNNN..... -- SVE predicate test
result.insLatency = PERFSCORE_LATENCY_1C;
result.insThroughput = PERFSCORE_THROUGHPUT_2C;
break;

case IF_SVE_DK_3A: // ........xx...... ..gggg.NNNNddddd -- SVE predicate count
result.insLatency = PERFSCORE_LATENCY_2C;
result.insThroughput = PERFSCORE_THROUGHPUT_2C;
break;

case IF_SVE_GE_4A: // ........xx.mmmmm ...gggnnnnn.DDDD -- SVE2 character match
case IF_SVE_HT_4A: // ........xx.mmmmm ...gggnnnnn.DDDD -- SVE floating-point compare vectors
result.insLatency = PERFSCORE_LATENCY_2C;
Expand Down

0 comments on commit 5167715

Please sign in to comment.