Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add ARM64 encodings for groups IF_SVE_CE,CF #98409

Merged
merged 11 commits into from
Feb 29, 2024
48 changes: 48 additions & 0 deletions src/coreclr/jit/codegenarm64test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4733,6 +4733,54 @@ void CodeGen::genArm64EmitterUnitTestsSve()
theEmitter->emitIns_R_R_R(INS_sve_lsr, EA_SCALABLE, REG_V0, REG_P0, REG_V0, INS_OPTS_SCALABLE_S,
INS_SCALABLE_OPTS_WIDE); // LSR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.D

// IF_SVE_CE_2A
theEmitter->emitIns_R_R(INS_sve_pmov, EA_SCALABLE, REG_P2, REG_V12, INS_OPTS_SCALABLE_B,
INS_SCALABLE_OPTS_TO_PREDICATE); // PMOV <Pd>.B, <Zn>
theEmitter->emitIns_R_R(INS_sve_pmov, EA_SCALABLE, REG_P7, REG_V2, INS_OPTS_SCALABLE_H,
INS_SCALABLE_OPTS_TO_PREDICATE); // PMOV <Pd>.H, <Zn>[0]

// IF_SVE_CE_2B
theEmitter->emitIns_R_R_I(INS_sve_pmov, EA_SCALABLE, REG_P15, REG_V7, 7, INS_OPTS_SCALABLE_D,
INS_SCALABLE_OPTS_TO_PREDICATE); // PMOV <Pd>.D, <Zn>[<imm>]
theEmitter->emitIns_R_R_I(INS_sve_pmov, EA_SCALABLE, REG_P7, REG_V16, 0, INS_OPTS_SCALABLE_D,
INS_SCALABLE_OPTS_TO_PREDICATE); // PMOV <Pd>.D, <Zn>[<imm>]

// IF_SVE_CE_2C
theEmitter->emitIns_R_R_I(INS_sve_pmov, EA_SCALABLE, REG_P0, REG_V31, 1, INS_OPTS_SCALABLE_H,
INS_SCALABLE_OPTS_TO_PREDICATE); // PMOV <Pd>.H, <Zn>[<imm>]
theEmitter->emitIns_R_R_I(INS_sve_pmov, EA_SCALABLE, REG_V1, REG_P1, 0, INS_OPTS_SCALABLE_H,
INS_SCALABLE_OPTS_TO_PREDICATE); // PMOV <Pd>.H, <Zn>[<imm>]

// IF_SVE_CE_2D
theEmitter->emitIns_R_R_I(INS_sve_pmov, EA_SCALABLE, REG_P3, REG_V9, 3, INS_OPTS_SCALABLE_S,
INS_SCALABLE_OPTS_TO_PREDICATE); // PMOV <Pd>.S, <Zn>[<imm>]
theEmitter->emitIns_R_R_I(INS_sve_pmov, EA_SCALABLE, REG_P10, REG_V4, 0, INS_OPTS_SCALABLE_S,
INS_SCALABLE_OPTS_TO_PREDICATE); // PMOV <Pd>.S, <Zn>[<imm>]

// IF_SVE_CF_2A
theEmitter->emitIns_R_R(INS_sve_pmov, EA_SCALABLE, REG_V11, REG_P12, INS_OPTS_SCALABLE_B,
INS_SCALABLE_OPTS_TO_VECTOR); // PMOV <Zd>, <Pn>.B
theEmitter->emitIns_R_R(INS_sve_pmov, EA_SCALABLE, REG_V2, REG_P7, INS_OPTS_SCALABLE_S,
INS_SCALABLE_OPTS_TO_VECTOR); // PMOV <Zd>[0], <Pn>.S

// IF_SVE_CF_2B
theEmitter->emitIns_R_R_I(INS_sve_pmov, EA_SCALABLE, REG_V6, REG_P8, 7, INS_OPTS_SCALABLE_D,
INS_SCALABLE_OPTS_TO_VECTOR); // PMOV <Zd>[<imm>], <Pn>.D
theEmitter->emitIns_R_R_I(INS_sve_pmov, EA_SCALABLE, REG_V9, REG_P7, 0, INS_OPTS_SCALABLE_D,
INS_SCALABLE_OPTS_TO_VECTOR); // PMOV <Zd>[<imm>], <Pn>.D

// IF_SVE_CF_2C
theEmitter->emitIns_R_R_I(INS_sve_pmov, EA_SCALABLE, REG_V8, REG_P4, 1, INS_OPTS_SCALABLE_H,
INS_SCALABLE_OPTS_TO_VECTOR); // PMOV <Zd>[<imm>], <Pn>.H
theEmitter->emitIns_R_R_I(INS_sve_pmov, EA_SCALABLE, REG_V5, REG_P9, 0, INS_OPTS_SCALABLE_H,
INS_SCALABLE_OPTS_TO_VECTOR); // PMOV <Zd>[<imm>], <Pn>.H

// IF_SVE_CF_2D
theEmitter->emitIns_R_R_I(INS_sve_pmov, EA_SCALABLE, REG_V14, REG_P2, 3, INS_OPTS_SCALABLE_S,
INS_SCALABLE_OPTS_TO_VECTOR); // PMOV <Zd>[<imm>], <Pn>.S
theEmitter->emitIns_R_R_I(INS_sve_pmov, EA_SCALABLE, REG_V3, REG_P15, 0, INS_OPTS_SCALABLE_S,
INS_SCALABLE_OPTS_TO_VECTOR); // PMOV <Zd>[<imm>], <Pn>.S

// IF_SVE_CJ_2A
theEmitter->emitIns_R_R(INS_sve_rev, EA_SCALABLE, REG_P1, REG_P2,
INS_OPTS_SCALABLE_B); // REV <Pd>.<T>, <Pn>.<T>
Expand Down
254 changes: 254 additions & 0 deletions src/coreclr/jit/emitarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1144,6 +1144,52 @@ void emitter::emitInsSanityCheck(instrDesc* id)
assert(isValidUimm4From1(emitGetInsSC(id)));
break;

case IF_SVE_CE_2A: // ................ ......nnnnn.DDDD -- SVE move predicate from vector
assert(isPredicateRegister(id->idReg1())); // DDDD
assert(isVectorRegister(id->idReg2())); // nnnnn
break;

case IF_SVE_CE_2B: // .........i...ii. ......nnnnn.DDDD -- SVE move predicate from vector
assert(isPredicateRegister(id->idReg1())); // DDDD
assert(isVectorRegister(id->idReg2())); // nnnnn
assert(isValidUimm<3>(emitGetInsSC(id)));
break;

case IF_SVE_CE_2C: // ..............i. ......nnnnn.DDDD -- SVE move predicate from vector
assert(isPredicateRegister(id->idReg1())); // DDDD
assert(isVectorRegister(id->idReg2())); // nnnnn
assert(isValidUimm<1>(emitGetInsSC(id))); // i
break;

case IF_SVE_CE_2D: // .............ii. ......nnnnn.DDDD -- SVE move predicate from vector
assert(isPredicateRegister(id->idReg1())); // DDDD
assert(isVectorRegister(id->idReg2())); // nnnnn
assert(isValidUimm<3>(emitGetInsSC(id))); // ii
break;

case IF_SVE_CF_2A: // ................ .......NNNNddddd -- SVE move predicate into vector
assert(isVectorRegister(id->idReg1())); // ddddd
assert(isPredicateRegister(id->idReg2())); // NNNN
break;

case IF_SVE_CF_2B: // .........i...ii. .......NNNNddddd -- SVE move predicate into vector
assert(isVectorRegister(id->idReg1())); // ddddd
assert(isPredicateRegister(id->idReg2())); // NNNN
assert(isValidUimm<3>(emitGetInsSC(id)));
break;

case IF_SVE_CF_2C: // ..............i. .......NNNNddddd -- SVE move predicate into vector
assert(isVectorRegister(id->idReg1())); // ddddd
assert(isPredicateRegister(id->idReg2())); // NNNN
assert(isValidUimm<1>(emitGetInsSC(id))); // i
break;

case IF_SVE_CF_2D: // .............ii. .......NNNNddddd -- SVE move predicate into vector
assert(isVectorRegister(id->idReg1())); // ddddd
assert(isPredicateRegister(id->idReg2())); // NNNN
assert(isValidUimm<2>(emitGetInsSC(id))); // ii
break;

case IF_SVE_CI_3A: // ........xx..MMMM .......NNNN.DDDD -- SVE permute predicate elements
elemsize = id->idOpSize();
assert(insOptsScalableStandard(id->idInsOpt()));
Expand Down Expand Up @@ -8775,6 +8821,30 @@ void emitter::emitIns_R_R(instruction ins,
}
break;

case INS_sve_pmov:
if (opt != INS_OPTS_SCALABLE_B)
{
assert(insOptsScalableStandard(opt));
return emitIns_R_R_I(INS_sve_pmov, attr, reg1, reg2, 0, opt, sopt);
}
if (sopt == INS_SCALABLE_OPTS_TO_PREDICATE)
{
assert(isPredicateRegister(reg1));
assert(isVectorRegister(reg2));
fmt = IF_SVE_CE_2A;
}
else if (sopt == INS_SCALABLE_OPTS_TO_VECTOR)
{
assert(isVectorRegister(reg1));
assert(isPredicateRegister(reg2));
fmt = IF_SVE_CF_2A;
}
else
{
assert(!"invalid instruction");
}
break;

case INS_sve_movs:
{
assert(opt == INS_OPTS_SCALABLE_B);
Expand Down Expand Up @@ -9817,6 +9887,57 @@ void emitter::emitIns_R_R_I(instruction ins,
fmt = IF_SVE_BB_2A;
break;

case INS_sve_pmov:
if (sopt == INS_SCALABLE_OPTS_TO_PREDICATE)
{
assert(isPredicateRegister(reg1));
assert(isVectorRegister(reg2));
switch (opt)
{
case INS_OPTS_SCALABLE_D:
assert(isValidUimm<3>(imm));
fmt = IF_SVE_CE_2B;
break;
case INS_OPTS_SCALABLE_S:
assert(isValidUimm<2>(imm));
fmt = IF_SVE_CE_2D;
break;
case INS_OPTS_SCALABLE_H:
assert(isValidUimm<1>(imm));
fmt = IF_SVE_CE_2C;
break;
default:
unreached();
}
}
else if (sopt == INS_SCALABLE_OPTS_TO_VECTOR)
{
assert(isVectorRegister(reg1));
assert(isPredicateRegister(reg2));
switch (opt)
{
case INS_OPTS_SCALABLE_D:
assert(isValidUimm<3>(imm));
fmt = IF_SVE_CF_2B;
break;
case INS_OPTS_SCALABLE_S:
assert(isValidUimm<2>(imm));
fmt = IF_SVE_CF_2D;
break;
case INS_OPTS_SCALABLE_H:
assert(isValidUimm<1>(imm));
fmt = IF_SVE_CF_2C;
break;
default:
unreached();
}
}
else
{
unreached();
}
break;

case INS_sve_sqrshrn:
case INS_sve_sqrshrun:
case INS_sve_uqrshrn:
Expand Down Expand Up @@ -19596,6 +19717,10 @@ void emitter::emitIns_Call(EmitCallType callType,

case IF_SVE_CZ_4A_A:
case IF_SVE_CZ_4A_L:
case IF_SVE_CE_2A:
case IF_SVE_CE_2B:
case IF_SVE_CE_2C:
case IF_SVE_CE_2D:
case IF_SVE_CF_2A:
case IF_SVE_CF_2B:
case IF_SVE_CF_2C:
Expand Down Expand Up @@ -23841,6 +23966,68 @@ BYTE* emitter::emitOutput_InstrSve(BYTE* dst, instrDesc* id)
dst += emitOutput_Instr(dst, code);
break;

case IF_SVE_CE_2A: // ................ ......nnnnn.DDDD -- SVE move predicate from vector
code = emitInsCodeSve(ins, fmt);
code |= insEncodeReg_P_3_to_0(id->idReg1()); // DDDD
code |= insEncodeReg_V_9_to_5(id->idReg2()); // nnnnn
dst += emitOutput_Instr(dst, code);
break;

case IF_SVE_CE_2B: // .........i...ii. ......nnnnn.DDDD -- SVE move predicate from vector
code = emitInsCodeSve(ins, fmt);
code |= insEncodeReg_P_3_to_0(id->idReg1()); // DDDD
code |= insEncodeReg_V_9_to_5(id->idReg2()); // nnnnn
code |= insEncodeSplitUimm<22, 22, 18, 17>(emitGetInsSC(id)); // i...ii
dst += emitOutput_Instr(dst, code);
break;

case IF_SVE_CE_2C: // ..............i. ......nnnnn.DDDD -- SVE move predicate from vector
code = emitInsCodeSve(ins, fmt);
code |= insEncodeReg_P_3_to_0(id->idReg1()); // DDDD
code |= insEncodeReg_V_9_to_5(id->idReg2()); // nnnnn
code |= insEncodeUimm<17, 17>(emitGetInsSC(id)); // i
dst += emitOutput_Instr(dst, code);
break;

case IF_SVE_CE_2D: // .............ii. ......nnnnn.DDDD -- SVE move predicate from vector
code = emitInsCodeSve(ins, fmt);
code |= insEncodeReg_P_3_to_0(id->idReg1()); // DDDD
code |= insEncodeReg_V_9_to_5(id->idReg2()); // nnnnn
code |= insEncodeUimm<18, 17>(emitGetInsSC(id)); // ii
dst += emitOutput_Instr(dst, code);
break;

case IF_SVE_CF_2A: // ................ .......NNNNddddd -- SVE move predicate into vector
code = emitInsCodeSve(ins, fmt);
code |= insEncodeReg_V_4_to_0(id->idReg1()); // ddddd
code |= insEncodeReg_P_8_to_5(id->idReg2()); // NNNN
dst += emitOutput_Instr(dst, code);
break;

case IF_SVE_CF_2B: // .........i...ii. .......NNNNddddd -- SVE move predicate into vector
code = emitInsCodeSve(ins, fmt);
code |= insEncodeReg_V_4_to_0(id->idReg1()); // ddddd
code |= insEncodeReg_P_8_to_5(id->idReg2()); // NNNN
code |= insEncodeSplitUimm<22, 22, 18, 17>(emitGetInsSC(id)); // i...ii
dst += emitOutput_Instr(dst, code);
break;

case IF_SVE_CF_2C: // ..............i. .......NNNNddddd -- SVE move predicate into vector
code = emitInsCodeSve(ins, fmt);
code |= insEncodeReg_V_4_to_0(id->idReg1()); // ddddd
code |= insEncodeReg_P_8_to_5(id->idReg2()); // NNNN
code |= insEncodeUimm<17, 17>(emitGetInsSC(id)); // i
dst += emitOutput_Instr(dst, code);
break;

case IF_SVE_CF_2D: // .............ii. .......NNNNddddd -- SVE move predicate into vector
code = emitInsCodeSve(ins, fmt);
code |= insEncodeReg_V_4_to_0(id->idReg1()); // ddddd
code |= insEncodeReg_P_8_to_5(id->idReg2()); // NNNN
code |= insEncodeUimm<18, 17>(emitGetInsSC(id)); // ii
dst += emitOutput_Instr(dst, code);
break;

case IF_SVE_CI_3A: // ........xx..MMMM .......NNNN.DDDD -- SVE permute predicate elements
code = emitInsCodeSve(ins, fmt);
code |= insEncodeReg_P_3_to_0(id->idReg1()); // DDDD
Expand Down Expand Up @@ -25733,6 +25920,18 @@ void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
emitDispComma();
}

//------------------------------------------------------------------------
// emitDispSveReg: Display a scalable vector register name
//
void emitter::emitDispSveReg(regNumber reg, bool addComma)
{
assert(isVectorRegister(reg));
printf(emitSveRegName(reg));

if (addComma)
emitDispComma();
}

//------------------------------------------------------------------------
// emitDispSveReg: Display a scalable vector register name with an arrangement suffix
//
Expand All @@ -25751,6 +25950,16 @@ void emitter::emitDispSveReg(regNumber reg, insOpts opt, bool addComma)
emitDispComma();
}

//------------------------------------------------------------------------
// emitDispSveRegIndex: Display a scalable vector register with indexed element
//
void emitter::emitDispSveRegIndex(regNumber reg, ssize_t index, bool addComma)
{
assert(isVectorRegister(reg));
printf(emitSveRegName(reg));
emitDispElementIndex(index, addComma);
}

//------------------------------------------------------------------------
// emitDispVectorReg: Display a SIMD vector register name with an arrangement suffix
//
Expand Down Expand Up @@ -27947,6 +28156,39 @@ void emitter::emitDispInsHelp(
emitDispSveReg(id->idReg3(), id->idInsOpt(), false); // mmmmm
break;

case IF_SVE_CE_2A: // ................ ......nnnnn.DDDD -- SVE move predicate from vector
emitDispPredicateReg(id->idReg1(), insGetPredicateType(fmt), INS_OPTS_SCALABLE_B, true); // DDDD
emitDispSveReg(id->idReg2(), false); // nnnnn
break;
case IF_SVE_CE_2B: // .........i...ii. ......nnnnn.DDDD -- SVE move predicate from vector
emitDispPredicateReg(id->idReg1(), insGetPredicateType(fmt), INS_OPTS_SCALABLE_D, true); // DDDD
emitDispSveRegIndex(id->idReg2(), emitGetInsSC(id), false); // nnnnn
break;
case IF_SVE_CE_2C: // ..............i. ......nnnnn.DDDD -- SVE move predicate from vector
emitDispPredicateReg(id->idReg1(), insGetPredicateType(fmt), INS_OPTS_SCALABLE_H, true); // DDDD
emitDispSveRegIndex(id->idReg2(), emitGetInsSC(id), false); // nnnnn
break;
case IF_SVE_CE_2D: // .............ii. ......nnnnn.DDDD -- SVE move predicate from vector
emitDispPredicateReg(id->idReg1(), insGetPredicateType(fmt), INS_OPTS_SCALABLE_S, true); // DDDD
emitDispSveRegIndex(id->idReg2(), emitGetInsSC(id), false); // nnnnn
break;
case IF_SVE_CF_2A: // ................ .......NNNNddddd -- SVE move predicate into vector
emitDispSveReg(id->idReg1(), true); // ddddd
emitDispPredicateReg(id->idReg2(), insGetPredicateType(fmt), INS_OPTS_SCALABLE_B, false); // NNNN
break;
case IF_SVE_CF_2B: // .........i...ii. .......NNNNddddd -- SVE move predicate into vector
emitDispSveRegIndex(id->idReg1(), emitGetInsSC(id), true); // ddddd
emitDispPredicateReg(id->idReg2(), insGetPredicateType(fmt), INS_OPTS_SCALABLE_D, false); // NNNN
break;
case IF_SVE_CF_2C: // ..............i. .......NNNNddddd -- SVE move predicate into vector
emitDispSveRegIndex(id->idReg1(), emitGetInsSC(id), true); // ddddd
emitDispPredicateReg(id->idReg2(), insGetPredicateType(fmt), INS_OPTS_SCALABLE_H, false); // NNNN
break;
case IF_SVE_CF_2D: // .............ii. .......NNNNddddd -- SVE move predicate into vector
emitDispSveRegIndex(id->idReg1(), emitGetInsSC(id), true); // ddddd
emitDispPredicateReg(id->idReg2(), insGetPredicateType(fmt), INS_OPTS_SCALABLE_S, false); // NNNN
break;

// <Pd>.<T>, <Pn>.<T>, <Pm>.<T>
case IF_SVE_CI_3A: // ........xx..MMMM .......NNNN.DDDD -- SVE permute predicate elements
emitDispPredicateReg(id->idReg1(), insGetPredicateType(fmt, 1), id->idInsOpt(), true); // DDDD
Expand Down Expand Up @@ -31763,6 +32005,18 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins
result.insLatency = PERFSCORE_LATENCY_2C;
break;

case IF_SVE_CE_2A: // ................ ......nnnnn.DDDD -- SVE move predicate from vector
case IF_SVE_CE_2B: // .........i...ii. ......nnnnn.DDDD -- SVE move predicate from vector
case IF_SVE_CE_2C: // ..............i. ......nnnnn.DDDD -- SVE move predicate from vector
case IF_SVE_CE_2D: // .............ii. ......nnnnn.DDDD -- SVE move predicate from vector
case IF_SVE_CF_2A: // ................ .......NNNNddddd -- SVE move predicate into vector
case IF_SVE_CF_2B: // .........i...ii. .......NNNNddddd -- SVE move predicate into vector
case IF_SVE_CF_2C: // ..............i. .......NNNNddddd -- SVE move predicate into vector
case IF_SVE_CF_2D: // .............ii. .......NNNNddddd -- SVE move predicate into vector
result.insThroughput = PERFSCORE_THROUGHPUT_140C; // @ToDo currently undocumented
result.insLatency = PERFSCORE_LATENCY_140C;
break;

case IF_SVE_CI_3A: // ........xx..MMMM .......NNNN.DDDD -- SVE permute predicate elements
case IF_SVE_CJ_2A: // ........xx...... .......NNNN.DDDD -- SVE reverse predicate elements
case IF_SVE_CK_2A: // ................ .......NNNN.DDDD -- SVE unpack predicate elements
Expand Down
Loading
Loading