Skip to content

Commit

Permalink
JIT ARM64-SVE2: Add IF_SVE_DQ_0A, IF_SVE_DR_1A, IF_SVE_DS_2A (#95996)
Browse files Browse the repository at this point in the history
  • Loading branch information
amanasifkhalid authored Dec 18, 2023
1 parent 435c323 commit 7693465
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 7 deletions.
12 changes: 12 additions & 0 deletions src/coreclr/jit/codegenarm64test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5120,6 +5120,18 @@ void CodeGen::genArm64EmitterUnitTestsSve()
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>

// IF_SVE_DQ_0A
theEmitter->emitIns_I(INS_sve_setffr, EA_PTRSIZE, 0); // SETFFR

// IF_SVE_DR_1A
theEmitter->emitIns_R(INS_sve_wrffr, EA_SCALABLE, REG_P0); // WRFFR <Pn>.B

// IF_SVE_DS_2A
theEmitter->emitIns_R_R(INS_sve_ctermeq, EA_8BYTE, REG_R0, REG_R1, INS_OPTS_NONE); // CTERMEQ <R><n>, <R><m>
theEmitter->emitIns_R_R(INS_sve_ctermeq, EA_4BYTE, REG_R2, REG_R3, INS_OPTS_NONE); // CTERMEQ <R><n>, <R><m>
theEmitter->emitIns_R_R(INS_sve_ctermne, EA_8BYTE, REG_R4, REG_R5, INS_OPTS_NONE); // CTERMNE <R><n>, <R><m>
theEmitter->emitIns_R_R(INS_sve_ctermne, EA_4BYTE, REG_R6, REG_R7, INS_OPTS_NONE); // CTERMNE <R><n>, <R><m>

// IF_SVE_GD_2A
theEmitter->emitIns_R_R(INS_sve_sqxtnb, EA_SCALABLE, REG_V0, REG_V5, INS_OPTS_SCALABLE_B); // SQXTNB <Zd>.<T>,
// <Zn>.<Tb>
Expand Down
107 changes: 100 additions & 7 deletions src/coreclr/jit/emitarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1189,6 +1189,21 @@ void emitter::emitInsSanityCheck(instrDesc* id)
assert(isScalableVectorSize(elemsize));
break;

case IF_SVE_DQ_0A: // ................ ................ -- SVE FFR initialise
break;

case IF_SVE_DR_1A: // ................ .......NNNN..... -- SVE FFR write from predicate
assert(id->idInsOpt() == INS_OPTS_SCALABLE_B);
assert(isPredicateRegister(id->idReg1())); // NNNN
break;

case IF_SVE_DS_2A: // .........x.mmmmm ......nnnnn..... -- SVE conditionally terminate scalars
assert(insOptsNone(id->idInsOpt()));
assert(isGeneralRegister(id->idReg1())); // nnnnn
assert(isGeneralRegister(id->idReg2())); // mmmmm
assert(isValidGeneralDatasize(id->idOpSize())); // x
break;

case IF_SVE_GD_2A: // .........x.xx... ......nnnnnddddd -- SVE2 saturating extract narrow
elemsize = id->idOpSize();
assert(insOptsScalableSimple(id->idInsOpt()));
Expand Down Expand Up @@ -1269,7 +1284,6 @@ bool emitter::emitInsMayWriteToGCReg(instrDesc* id)

case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov - to general)
case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov - to general)

return true;

case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
Expand Down Expand Up @@ -5611,6 +5625,12 @@ void emitter::emitIns_I(instruction ins, emitAttr attr, ssize_t imm)
assert(!"Instruction cannot be encoded: IF_SI_0A");
}
}
else if (ins == INS_sve_setffr)
{
fmt = IF_SVE_DQ_0A;
attr = EA_PTRSIZE;
imm = 0;
}
else
{
unreached();
Expand All @@ -5634,43 +5654,46 @@ void emitter::emitIns_I(instruction ins, emitAttr attr, ssize_t imm)
void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg)
{
insFormat fmt = IF_NONE;
instrDesc* id = nullptr;
instrDesc* id = emitNewInstrSmall(attr);

/* Figure out the encoding format of the instruction */
switch (ins)
{
case INS_br:
case INS_ret:
assert(isGeneralRegister(reg));
id = emitNewInstrSmall(attr);
id->idReg1(reg);
fmt = IF_BR_1A;
break;

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

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

case INS_sve_aesmc:
case INS_sve_aesimc:
id = emitNewInstrSmall(attr);
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_wrffr:
id->idInsOpt(INS_OPTS_SCALABLE_B);
id->idReg1(reg);
assert(isPredicateRegister(reg)); // NNNN
fmt = IF_SVE_DR_1A;
break;

default:
unreached();
}
Expand Down Expand Up @@ -6861,6 +6884,15 @@ void emitter::emitIns_R_R(
}
break;

case INS_sve_ctermeq:
case INS_sve_ctermne:
assert(insOptsNone(opt));
assert(isGeneralRegister(reg1)); // nnnnn
assert(isGeneralRegister(reg2)); // mmmmm
assert(isValidGeneralDatasize(size)); // x
fmt = IF_SVE_DS_2A;
break;

case INS_sve_sqxtnb:
case INS_sve_sqxtnt:
case INS_sve_uqxtnb:
Expand Down Expand Up @@ -11759,7 +11791,7 @@ void emitter::emitIns_Call(EmitCallType callType,
{
assert(isIntegerRegister(reg));
emitter::code_t ureg = (emitter::code_t)reg;
assert((ureg >= 0) && (ureg <= 31));
assert((ureg >= 12) && (ureg <= 15));
return ureg << 16;
}

Expand Down Expand Up @@ -12741,6 +12773,22 @@ void emitter::emitIns_Call(EmitCallType callType,
return encodedSize | imm3High | imm3Low;
}

/*****************************************************************************
*
* Returns the encoding to select the <R> 4/8-byte width specifier <R>
* at bit location 22 for an Arm64 Sve instruction.
*/
/*static*/ emitter::code_t emitter::insEncodeSveElemsize_R_22(emitAttr size)
{
if (size == EA_8BYTE)
{
return 0x400000; // set the bit at location 22
}

assert(size == EA_4BYTE);
return 0;
}

BYTE* emitter::emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, instrDescJmp* id)
{
instruction ins = id->idIns();
Expand Down Expand Up @@ -14801,6 +14849,25 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
dst += emitOutput_Instr(dst, code);
break;

case IF_SVE_DQ_0A: // ................ ................ -- SVE FFR initialise
code = emitInsCodeSve(ins, fmt);
dst += emitOutput_Instr(dst, code);
break;

case IF_SVE_DR_1A: // ................ .......NNNN..... -- SVE FFR write from predicate
code = emitInsCodeSve(ins, fmt);
code |= insEncodeReg_P_8_to_5(id->idReg1()); // NNNN
dst += emitOutput_Instr(dst, code);
break;

case IF_SVE_DS_2A: // .........x.mmmmm ......nnnnn..... -- SVE conditionally terminate scalars
code = emitInsCodeSve(ins, fmt);
code |= insEncodeReg_R_9_to_5(id->idReg1()); // nnnnn
code |= insEncodeReg_R_20_to_16(id->idReg2()); // mmmmm
code |= insEncodeSveElemsize_R_22(id->idOpSize()); // x
dst += emitOutput_Instr(dst, code);
break;

case IF_SVE_GD_2A: // .........x.xx... ......nnnnnddddd -- SVE2 saturating extract narrow
code = emitInsCodeSve(ins, fmt);
code |= insEncodeReg_V_4_to_0(id->idReg1()); // ddddd
Expand Down Expand Up @@ -17211,6 +17278,21 @@ void emitter::emitDispInsHelp(
emitDispImm(emitGetInsSC(id), false); // iiii
break;

// none
case IF_SVE_DQ_0A: // ................ ................ -- SVE FFR initialise
break;

// <Pn>.B
case IF_SVE_DR_1A: // ................ .......NNNN..... -- SVE FFR write from predicate
emitDispPredicateReg(id->idReg1(), PREDICATE_SIZED, id->idInsOpt(), false); // NNNN
break;

// <R><n>, <R><m>
case IF_SVE_DS_2A: // .........x.mmmmm ......nnnnn..... -- SVE conditionally terminate scalars
emitDispReg(id->idReg1(), id->idOpSize(), true); // nnnnn
emitDispReg(id->idReg2(), id->idOpSize(), false); // mmmmm
break;

// <Zd>.<T>, <Zn>.<Tb>
case IF_SVE_GD_2A: // .........x.xx... ......nnnnnddddd -- SVE2 saturating extract narrow
emitDispSveReg(id->idReg1(), id->idInsOpt(), true); // ddddd
Expand Down Expand Up @@ -19723,6 +19805,17 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins
}
break;

case IF_SVE_DQ_0A: // ................ ................ -- SVE FFR initialise
case IF_SVE_DR_1A: // ................ .......NNNN..... -- SVE FFR write from predicate
result.insThroughput = PERFSCORE_THROUGHPUT_1C;
result.insLatency = PERFSCORE_LATENCY_2C;
break;

case IF_SVE_DS_2A: // .........x.mmmmm ......nnnnn..... -- SVE conditionally terminate scalars
result.insThroughput = PERFSCORE_THROUGHPUT_1C;
result.insLatency = PERFSCORE_LATENCY_1C;
break;

// Not available in Arm Neoverse N2 Software Optimization Guide.
case IF_SVE_AG_3A: // ........xx...... ...gggnnnnnddddd -- SVE bitwise logical reduction (quadwords)
case IF_SVE_AJ_3A: // ........xx...... ...gggnnnnnddddd -- SVE integer add reduction (quadwords)
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/jit/emitarm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,10 @@ static code_t insEncodeSveElemsize_tszh_22_tszl_20_to_19(emitAttr size);
// This specifically encodes the field 'tszh:tszl' at bit locations '23-22:9-8'.
static code_t insEncodeSveShift_23_to_22_9_to_0(emitAttr size, bool isRightShift, size_t imm);

// Returns the encoding to select the 4/8-byte width specifier <R> at bit location 22
// for an Arm64 Sve instruction.
static code_t insEncodeSveElemsize_R_22(emitAttr size);

// Returns true if 'reg' represents an integer register.
static bool isIntegerRegister(regNumber reg)
{
Expand Down

0 comments on commit 7693465

Please sign in to comment.