Skip to content
Merged
42 changes: 42 additions & 0 deletions src/coreclr/jit/codegenarm64test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4725,6 +4725,48 @@ 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); // PMOV <Pd>.B, <Zn>

// IF_SVE_CE_2B
theEmitter->emitIns_R_R_I(INS_sve_pmov, EA_SCALABLE, REG_P15, REG_V7, 7,
INS_OPTS_SCALABLE_D); // PMOV <Pd>.D, <Zn>[<imm>]
theEmitter->emitIns_R_R_I(INS_sve_pmov, EA_SCALABLE, REG_P7, REG_V16, 0,
INS_OPTS_SCALABLE_D); // 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); // PMOV <Pd>.H, <Zn>[<imm>]
theEmitter->emitIns_R_R_I(INS_sve_pmov, EA_SCALABLE, REG_V1, REG_P1, 0,
INS_OPTS_SCALABLE_H); // 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); // PMOV <Pd>.S, <Zn>[<imm>]
theEmitter->emitIns_R_R_I(INS_sve_pmov, EA_SCALABLE, REG_P10, REG_V4, 0,
INS_OPTS_SCALABLE_S); // PMOV <Pd>.S, <Zn>[<imm>]

// IF_SVE_CF_2A
theEmitter->emitIns_R_R(INS_sve_pmov, EA_SCALABLE, REG_V11, REG_P12); // PMOV <Zd>, <Pn>.B

// IF_SVE_CF_2B
theEmitter->emitIns_R_R_I(INS_sve_pmov, EA_SCALABLE, REG_V6, REG_P8, 7,
INS_OPTS_SCALABLE_D); // PMOV <Zd>[<imm>], <Pn>.D
theEmitter->emitIns_R_R_I(INS_sve_pmov, EA_SCALABLE, REG_V9, REG_P7, 0,
INS_OPTS_SCALABLE_D); // 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); // PMOV <Zd>[<imm>], <Pn>.H
theEmitter->emitIns_R_R_I(INS_sve_pmov, EA_SCALABLE, REG_V5, REG_P9, 0,
INS_OPTS_SCALABLE_H); // 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); // PMOV <Zd>[<imm>], <Pn>.S
theEmitter->emitIns_R_R_I(INS_sve_pmov, EA_SCALABLE, REG_V3, REG_P15, 0,
INS_OPTS_SCALABLE_S); // 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
240 changes: 240 additions & 0 deletions src/coreclr/jit/emitarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1094,6 +1094,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 @@ -8319,6 +8365,21 @@ void emitter::emitIns_R_R(instruction ins,
}
break;

case INS_sve_pmov:
if (isPredicateRegister(reg1) && isVectorRegister(reg2))
{
fmt = IF_SVE_CE_2A;
}
else if (isVectorRegister(reg1) && 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 @@ -9203,6 +9264,48 @@ void emitter::emitIns_R_R_I(instruction ins,
fmt = IF_SVE_AM_2A;
break;

case INS_sve_pmov:
switch (opt)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might be better to rewrite this switch/case something like this:

if (isPredicateRegister(reg1) && isVectorRegister(reg2))
{
    switch (opt)
    {
        case INS_OPTS_SCALABLE_D:
            assert(isValidUimm3(imm));
            fmt = IF_SVE_CE_2B;
            break;
        case INS_OPTS_SCALABLE_S:
            assert(isValidUimm2(imm));
            fmt = IF_SVE_CE_2D;
            break;
        case INS_OPTS_SCALABLE_H:
            assert(isValidImm1(imm));
            fmt = IF_SVE_CE_2C;
            break;
        default:
            unreached();
    }
}
else if (isVectorRegister(reg1) && isPredicateRegister(reg2))
{
    switch (opt)
    {
        case INS_OPTS_SCALABLE_D:
            assert(isValidUimm3(imm));
            fmt = IF_SVE_CF_2B;
            break;
        case INS_OPTS_SCALABLE_S:
            assert(isValidUimm2(imm));
            fmt = IF_SVE_CF_2D;
            break;
        case INS_OPTS_SCALABLE_H:
            assert(isValidImm1(imm));
            fmt = IF_SVE_CF_2C;
            break;
        default:
            unreached();
    }
}
else
{
  unreached();
}

{
case INS_OPTS_SCALABLE_D:
assert(isValidUimm3(imm));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use the new methods that you have, here and elsewhere.

if (isPredicateRegister(reg1) && isVectorRegister(reg2))
{
fmt = IF_SVE_CE_2B;
}
else if (isVectorRegister(reg1) && isPredicateRegister(reg2))
{
fmt = IF_SVE_CF_2B;
}
break;
case INS_OPTS_SCALABLE_S:
assert(isValidUimm2(imm));
if (isPredicateRegister(reg1) && isVectorRegister(reg2))
{
fmt = IF_SVE_CE_2D;
}
else if (isVectorRegister(reg1) && isPredicateRegister(reg2))
{
fmt = IF_SVE_CF_2D;
}
break;
case INS_OPTS_SCALABLE_H:
assert(isValidImm1(imm));
if (isPredicateRegister(reg1) && isVectorRegister(reg2))
{
fmt = IF_SVE_CE_2C;
}
else if (isVectorRegister(reg1) && isPredicateRegister(reg2))
{
fmt = IF_SVE_CF_2C;
}
break;
default:
break;
}
assert(fmt != IF_NONE && "invalid combination of size and register type specified");
break;

case INS_sve_sqrshrn:
case INS_sve_sqrshrun:
case INS_sve_uqrshrn:
Expand Down Expand Up @@ -17432,6 +17535,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 @@ -21260,6 +21367,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 @@ -22725,6 +22894,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("%s", emitSveRegName(reg));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
printf("%s", emitSveRegName(reg));
printf(emitSveRegName(reg));


if (addComma)
emitDispComma();
}

//------------------------------------------------------------------------
// emitDispSveReg: Display a scalable vector register name with an arrangement suffix
//
Expand All @@ -22739,6 +22920,20 @@ 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("%s", emitSveRegName(reg));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
printf("%s", emitSveRegName(reg));
printf(emitSveRegName(reg));


printf("[%d]", static_cast<int>(index));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we have emitDispElementIndex which will do this.

So something like this:

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

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
printf("[%d]", static_cast<int>(index));
printf("[%d]", (int)index);


if (addComma)
emitDispComma();
}

//------------------------------------------------------------------------
// emitDispVectorReg: Display a SIMD vector register name with an arrangement suffix
//
Expand Down Expand Up @@ -24730,6 +24925,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->idReg2(), 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 @@ -28098,6 +28326,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