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

JIT: Added ARM64 SVE_GA_2A encoding #95435

Merged
merged 13 commits into from
Dec 4, 2023
19 changes: 19 additions & 0 deletions src/coreclr/jit/codegenarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10513,6 +10513,25 @@ void CodeGen::genArm64EmitterUnitTests()
INS_OPTS_SCALABLE_D); /* REVH <Zd>.<T>, <Pg>/M, <Zn>.<T> */
theEmitter->emitIns_R_R_R(INS_sve_revw, EA_SCALABLE, REG_V25, REG_P4, REG_V16,
INS_OPTS_SCALABLE_D); /* REVW <Zd>.D, <Pg>/M, <Zn>.D */
// IF_SVE_GA_2A
theEmitter->emitIns_R_R_I(INS_sve_sqrshrn, EA_SCALABLE, REG_V0, REG_V0, 5,
TIHan marked this conversation as resolved.
Show resolved Hide resolved
INS_OPTS_SCALABLE_H); // SQRSHRN <Zd>.H, {<Zn1>.S-<Zn2>.S }, #<const>
theEmitter->emitIns_R_R_I(INS_sve_sqrshrun, EA_SCALABLE, REG_V0, REG_V0, 5,
INS_OPTS_SCALABLE_H); // SQRSHRUN <Zd>.H, {<Zn1>.S-<Zn2>.S }, #<const>
theEmitter->emitIns_R_R_I(INS_sve_uqrshrn, EA_SCALABLE, REG_V0, REG_V0, 5,
INS_OPTS_SCALABLE_H); // UQRSHRN <Zd>.H, {<Zn1>.S-<Zn2>.S }, #<const>
theEmitter->emitIns_R_R_I(INS_sve_sqrshrn, EA_SCALABLE, REG_V0, REG_V2, 16,
INS_OPTS_SCALABLE_H); // SQRSHRN <Zd>.H, {<Zn1>.S-<Zn2>.S }, #<const>
theEmitter->emitIns_R_R_I(INS_sve_sqrshrun, EA_SCALABLE, REG_V0, REG_V4, 7,
INS_OPTS_SCALABLE_H); // SQRSHRUN <Zd>.H, {<Zn1>.S-<Zn2>.S }, #<const>
theEmitter->emitIns_R_R_I(INS_sve_uqrshrn, EA_SCALABLE, REG_V0, REG_V6, 1,
INS_OPTS_SCALABLE_H); // UQRSHRN <Zd>.H, {<Zn1>.S-<Zn2>.S }, #<const>
theEmitter->emitIns_R_R_I(INS_sve_sqrshrn, EA_SCALABLE, REG_V30, REG_V16, 16,
INS_OPTS_SCALABLE_H); // SQRSHRN <Zd>.H, {<Zn1>.S-<Zn2>.S }, #<const>
theEmitter->emitIns_R_R_I(INS_sve_sqrshrun, EA_SCALABLE, REG_V16, REG_V8, 7,
INS_OPTS_SCALABLE_H); // SQRSHRUN <Zd>.H, {<Zn1>.S-<Zn2>.S }, #<const>
theEmitter->emitIns_R_R_I(INS_sve_uqrshrn, EA_SCALABLE, REG_V15, REG_V12, 1,
INS_OPTS_SCALABLE_H); // UQRSHRN <Zd>.H, {<Zn1>.S-<Zn2>.S }, #<const>

#endif // ALL_ARM64_EMITTER_UNIT_TESTS_SVE

Expand Down
115 changes: 115 additions & 0 deletions src/coreclr/jit/emitarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1117,6 +1117,13 @@ void emitter::emitInsSanityCheck(instrDesc* id)
assert(isValidScalarDatasize(elemsize));
break;

case IF_SVE_GA_2A: // ............iiii ......nnnn.ddddd -- SME2 multi-vec shift narrow
elemsize = id->idOpSize();
assert(isVectorRegister(id->idReg1())); // nnnn
assert(isVectorRegister(id->idReg2())); // ddddd
assert(id->idInsOpt() == INS_OPTS_SCALABLE_H);
break;

default:
printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
assert(!"Unexpected format");
Expand Down Expand Up @@ -1713,6 +1720,18 @@ emitter::insFormat emitter::emitInsFormat(instruction ins)
#define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) info,
#define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) info,
#include "instrs.h"
#define INST1(id, nm, info, fmt, e1 ) info,
#define INST2(id, nm, info, fmt, e1, e2 ) info,
#define INST3(id, nm, info, fmt, e1, e2, e3 ) info,
#define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) info,
#define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) info,
#define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) info,
#define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) info,
#define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) info,
#define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) info,
#define INST11(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10,e11 ) info,
#define INST13(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13) info,
#include "instrsarm64sve.h"
};
// clang-format on

Expand Down Expand Up @@ -7367,6 +7386,18 @@ void emitter::emitIns_R_R_I(
fmt = IF_LS_2E;
break;

case INS_sve_sqrshrn:
case INS_sve_sqrshrun:
case INS_sve_uqrshrn:
isRightShift = emitInsIsVectorRightShift(ins);
assert(isVectorRegister(reg1));
assert(isVectorRegister(reg2));
assert(opt == INS_OPTS_SCALABLE_H);
assert(isRightShift); // These are always right-shift.
assert(isValidVectorShiftAmount(imm, EA_4BYTE, isRightShift));
fmt = IF_SVE_GA_2A;
break;

default:
unreached();
break;
Expand Down Expand Up @@ -11454,6 +11485,22 @@ void emitter::emitIns_Call(EmitCallType callType,
return ureg << 6;
}

/*****************************************************************************
*
* Return an encoding for the specified 'V' register used in '9' thru '6' position with the times two encoding.
* This encoding requires that the register number be divisible by two.
*/

/*static*/ emitter::code_t emitter::insEncodeReg_V_9_to_6_Times_Two(regNumber reg)
{
assert(isVectorRegister(reg));
emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
assert(ureg % 2 == 0);
ureg /= 2u;
assert((ureg >= 0) && (ureg <= 32));
return ureg << 6;
}

/*****************************************************************************
*
* Returns an encoding for the specified condition code.
Expand Down Expand Up @@ -14296,6 +14343,18 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
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);
assert(emitInsIsVectorRightShift(id->idIns()));
assert(isValidVectorShiftAmount(imm, EA_4BYTE, /* rightShift */ true));
code = emitInsCodeSve(ins, fmt);
code |= insEncodeVectorShift(EA_4BYTE, /* right-shift */ -imm); // iiii
TIHan marked this conversation as resolved.
Show resolved Hide resolved
code |= insEncodeReg_V_4_to_0(id->idReg1()); // ddddd
code |= insEncodeReg_V_9_to_6_Times_Two(id->idReg2()); // nnnn
dst += emitOutput_Instr(dst, code);
break;

default:
assert(!"Unexpected format");
break;
Expand Down Expand Up @@ -14848,6 +14907,30 @@ void emitter::emitDispVectorElemList(
}
}

//------------------------------------------------------------------------
// emitDispSveRegList: Display a SVE vector register list
//
void emitter::emitDispSveRegList(regNumber firstReg, unsigned listSize, insOpts opt, bool addComma)
{
assert(isVectorRegister(firstReg));

regNumber currReg = firstReg;

printf("{ ");
for (unsigned i = 0; i < listSize; i++)
{
const bool notLastRegister = (i != listSize - 1);
emitDispSveReg(currReg, opt, notLastRegister);
currReg = (currReg == REG_V31) ? REG_V0 : REG_NEXT(currReg);
}
printf(" }");

if (addComma)
{
emitDispComma();
}
}

//------------------------------------------------------------------------
// emitDispPredicateReg: Display a predicate register name with with an arrangement suffix
//
Expand Down Expand Up @@ -16606,6 +16689,12 @@ void emitter::emitDispInsHelp(
emitDispReg(encodingZRtoSP(id->idReg3()), size, false); // mmmmm
break;

case IF_SVE_GA_2A: // ............iiii ......nnnn.ddddd -- SME2 multi-vec shift narrow
TIHan marked this conversation as resolved.
Show resolved Hide resolved
emitDispSveReg(id->idReg1(), id->idInsOpt(), true); // ddddd
emitDispSveRegList(id->idReg2(), 2, INS_OPTS_SCALABLE_S, true); // nnnn
emitDispImm(emitGetInsSC(id), false); // iiii
TIHan marked this conversation as resolved.
Show resolved Hide resolved
break;

default:
printf("unexpected format %s", emitIfName(id->idInsFmt()));
assert(!"unexpectedFormat");
Expand Down Expand Up @@ -19006,6 +19095,32 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins
result.insThroughput = PERFSCORE_THROUGHPUT_25C; // TODO-SVE: Placeholder
break;

// Not available in Arm Neoverse N2 Software Optimization Guide.
case IF_SVE_GA_2A: // ............iiii ......nnnn.ddddd -- SME2 multi-vec shift narrow
switch (ins)
TIHan marked this conversation as resolved.
Show resolved Hide resolved
{
case INS_sve_sqrshrn:
result.insThroughput = PERFSCORE_THROUGHPUT_25C; // TODO-SVE: Placeholder
result.insLatency = PERFSCORE_LATENCY_20C; // TODO-SVE: Placeholder
break;

case INS_sve_sqrshrun:
result.insThroughput = PERFSCORE_THROUGHPUT_25C; // TODO-SVE: Placeholder
result.insLatency = PERFSCORE_LATENCY_20C; // TODO-SVE: Placeholder
break;

case INS_sve_uqrshrn:
result.insThroughput = PERFSCORE_THROUGHPUT_25C; // TODO-SVE: Placeholder
result.insLatency = PERFSCORE_LATENCY_20C; // TODO-SVE: Placeholder
break;

default:
// all other instructions
perfScoreUnhandledInstruction(id, &result);
break;
}
break;

default:
// all other instructions
perfScoreUnhandledInstruction(id, &result);
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/jit/emitarm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ void emitDispVectorReg(regNumber reg, insOpts opt, bool addComma);
void emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma);
void emitDispVectorRegList(regNumber firstReg, unsigned listSize, insOpts opt, bool addComma);
void emitDispVectorElemList(regNumber firstReg, unsigned listSize, emitAttr elemsize, unsigned index, bool addComma);
void emitDispSveRegList(regNumber firstReg, unsigned listSize, insOpts opt, bool addComma);
void emitDispPredicateReg(regNumber reg, PredicateType ptype, bool addComma);
void emitDispLowPredicateReg(regNumber reg, PredicateType ptype, bool addComma);
void emitDispArrangement(insOpts opt);
Expand Down Expand Up @@ -378,6 +379,10 @@ static code_t insEncodeReg_V_20_to_17(regNumber reg);
// Return an encoding for the specified 'V' register used in '9' thru '6' position.
static code_t insEncodeReg_V_9_to_6(regNumber reg);

// Return an encoding for the specified 'V' register used in '9' thru '6' position with the times two encoding.
// This encoding requires that the register number be divisible by two.
static code_t insEncodeReg_V_9_to_6_Times_Two(regNumber reg);

// Returns an encoding for the imm which represents the condition code.
static code_t insEncodeCond(insCond cond);

Expand Down
Loading