Skip to content

Commit

Permalink
Add Arm64 encodings for IF_SVE_CY_3A and IF_SVE_CY_3B group (#96992)
Browse files Browse the repository at this point in the history
* Add Arm64 encodings for IF_SVE_CY_3A and IF_SVE_CY_3B group

* Fix function declaration

---------

Co-authored-by: Kunal Pathak <Kunal.Pathak@microsoft.com>
  • Loading branch information
SwapnilGaikwad and kunalspathak authored Jan 17, 2024
1 parent 3ffa1a9 commit 08cff56
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 4 deletions.
24 changes: 24 additions & 0 deletions src/coreclr/jit/codegenarm64test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4794,6 +4794,30 @@ void CodeGen::genArm64EmitterUnitTestsSve()
theEmitter->emitIns_R_R_R_R(INS_sve_cmpne, EA_SCALABLE, REG_P0, REG_P0, REG_V14, REG_V28, INS_OPTS_SCALABLE_B,
INS_SCALABLE_OPTS_WIDE); /* CMPNE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.D */

// IF_SVE_CY_3A
theEmitter->emitIns_R_R_R_I(INS_sve_cmpeq, EA_SCALABLE, REG_P15, REG_P0, REG_V31, 8,
INS_OPTS_SCALABLE_B); /* CMPEQ <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm> */
theEmitter->emitIns_R_R_R_I(INS_sve_cmpge, EA_SCALABLE, REG_P11, REG_P7, REG_V21, 1,
INS_OPTS_SCALABLE_H); /* CMPGE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm> */
theEmitter->emitIns_R_R_R_I(INS_sve_cmpgt, EA_SCALABLE, REG_P10, REG_P1, REG_V18, 4,
INS_OPTS_SCALABLE_S); /* CMPGT <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm> */
theEmitter->emitIns_R_R_R_I(INS_sve_cmple, EA_SCALABLE, REG_P8, REG_P6, REG_V11, 15,
INS_OPTS_SCALABLE_D); /* CMPLE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm> */
theEmitter->emitIns_R_R_R_I(INS_sve_cmplt, EA_SCALABLE, REG_P7, REG_P2, REG_V8, -16,
INS_OPTS_SCALABLE_B); /* CMPLT <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm> */
theEmitter->emitIns_R_R_R_I(INS_sve_cmpne, EA_SCALABLE, REG_P0, REG_P5, REG_V0, -14,
INS_OPTS_SCALABLE_H); /* CMPNE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm> */

// IF_SVE_CY_3B
theEmitter->emitIns_R_R_R_I(INS_sve_cmphi, EA_SCALABLE, REG_P15, REG_P7, REG_V19, 0,
INS_OPTS_SCALABLE_B); /* CMPHI <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm> */
theEmitter->emitIns_R_R_R_I(INS_sve_cmphs, EA_SCALABLE, REG_P11, REG_P1, REG_V0, 36,
INS_OPTS_SCALABLE_H); /* CMPHS <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm> */
theEmitter->emitIns_R_R_R_I(INS_sve_cmplo, EA_SCALABLE, REG_P8, REG_P5, REG_V21, 64,
INS_OPTS_SCALABLE_S); /* CMPLO <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm> */
theEmitter->emitIns_R_R_R_I(INS_sve_cmpls, EA_SCALABLE, REG_P0, REG_P3, REG_V9, 127,
INS_OPTS_SCALABLE_D); /* CMPLS <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm> */

// 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
117 changes: 113 additions & 4 deletions src/coreclr/jit/emitarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1072,8 +1072,28 @@ void emitter::emitInsSanityCheck(instrDesc* id)
assert(insOptsScalableWide(id->idInsOpt())); // xx
assert(isPredicateRegister(id->idReg1())); // DDDD
assert(isLowPredicateRegister(id->idReg2())); // ggg
assert(isVectorRegister(id->idReg3())); // mmmmm
assert(isVectorRegister(id->idReg4())); // nnnnn
assert(isVectorRegister(id->idReg3())); // nnnnn
assert(isVectorRegister(id->idReg4())); // mmmmm
break;

case IF_SVE_CY_3A: // ........xx.iiiii ...gggnnnnn.DDDD -- SVE integer compare with signed immediate
elemsize = id->idOpSize();
assert(isScalableVectorSize(elemsize));
assert(insOptsScalableStandard(id->idInsOpt()));
assert(isPredicateRegister(id->idReg1())); // DDDD
assert(isLowPredicateRegister(id->idReg2())); // ggg
assert(isVectorRegister(id->idReg3())); // nnnnn
assert(isValidSimm5(emitGetInsSC(id))); // iiiii
break;

case IF_SVE_CY_3B: // ........xx.iiiii ii.gggnnnnn.DDDD -- SVE integer compare with unsigned immediate
elemsize = id->idOpSize();
assert(isScalableVectorSize(elemsize));
assert(insOptsScalableStandard(id->idInsOpt()));
assert(isPredicateRegister(id->idReg1())); // DDDD
assert(isLowPredicateRegister(id->idReg2())); // ggg
assert(isVectorRegister(id->idReg3())); // nnnnn
assert(isValidUimm7(emitGetInsSC(id))); // iiiii
break;

case IF_SVE_GE_4A: // ........xx.mmmmm ...gggnnnnn.DDDD -- SVE2 character match
Expand Down Expand Up @@ -9639,6 +9659,32 @@ void emitter::emitIns_R_R_R_I(instruction ins,
}
break;

case INS_sve_cmpeq:
case INS_sve_cmpgt:
case INS_sve_cmpge:
case INS_sve_cmpne:
case INS_sve_cmple:
case INS_sve_cmplt:
assert(insOptsScalableStandard(opt));
assert(isPredicateRegister(reg1)); // DDDD
assert(isLowPredicateRegister(reg2)); // ggg
assert(isVectorRegister(reg3)); // nnnnn
assert(isValidSimm5(imm)); // iiiii
fmt = IF_SVE_CY_3A;
break;

case INS_sve_cmphi:
case INS_sve_cmphs:
case INS_sve_cmplo:
case INS_sve_cmpls:
assert(insOptsScalableStandard(opt));
assert(isPredicateRegister(reg1)); // DDDD
assert(isLowPredicateRegister(reg2)); // ggg
assert(isVectorRegister(reg3)); // nnnnn
assert(isValidUimm7(imm)); // iiiii
fmt = IF_SVE_CY_3B;
break;

case INS_fmul: // by element, imm[0..3] selects the element of reg3
case INS_fmla:
case INS_fmls:
Expand Down Expand Up @@ -14348,6 +14394,32 @@ void emitter::emitIns_Call(EmitCallType callType,
return insEncodeSimm4_19_to_16(imm / 32);
}

/*****************************************************************************
*
* Returns the encoding for the immediate value as 5-bits at bit locations '20-16'.
*/

/*static*/ emitter::code_t emitter::insEncodeSimm5_20_to_16(ssize_t imm)
{
assert(isValidSimm5(imm));
if (imm < 0)
{
imm = (imm & 0x1F);
}
return (code_t)imm << 16;
}

/*****************************************************************************
*
* Returns the encoding for the immediate value as 7-bits at bit locations '20-14'.
*/

/*static*/ emitter::code_t emitter::insEncodeUimm7_20_to_14(ssize_t imm)
{
assert(isValidUimm7(imm));
return (code_t)imm << 14;
}

/*****************************************************************************
*
* Returns the encoding to select the <R> 4/8-byte width specifier <R>
Expand Down Expand Up @@ -16439,6 +16511,28 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
dst += emitOutput_Instr(dst, code);
break;

case IF_SVE_CY_3A: // ........xx.iiiii ...gggnnnnn.DDDD -- SVE integer compare with signed immediate
imm = emitGetInsSC(id);
code = emitInsCodeSve(ins, fmt);
code |= insEncodeReg_P_3_to_0(id->idReg1()); // DDDD
code |= insEncodeReg_P_12_to_10(id->idReg2()); // ggg
code |= insEncodeReg_V_9_to_5(id->idReg3()); // nnnnn
code |= insEncodeSimm5_20_to_16(imm); // iiiii
code |= insEncodeElemsize(optGetSveElemsize(id->idInsOpt())); // xx
dst += emitOutput_Instr(dst, code);
break;

case IF_SVE_CY_3B: // ........xx.iiiii ii.gggnnnnn.DDDD -- SVE integer compare with unsigned immediate
imm = emitGetInsSC(id);
code = emitInsCodeSve(ins, fmt);
code |= insEncodeReg_P_3_to_0(id->idReg1()); // DDDD
code |= insEncodeReg_P_12_to_10(id->idReg2()); // ggg
code |= insEncodeReg_V_9_to_5(id->idReg3()); // nnnnn
code |= insEncodeUimm7_20_to_14(imm); // iiiii
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 @@ -19109,8 +19203,17 @@ void emitter::emitDispInsHelp(
case IF_SVE_CX_4A_A: // ........xx.mmmmm ...gggnnnnn.DDDD -- SVE integer compare vectors
emitDispPredicateReg(id->idReg1(), PREDICATE_SIZED, id->idInsOpt(), true); // DDDD
emitDispPredicateReg(id->idReg2(), PREDICATE_ZERO, id->idInsOpt(), true); // ggg
emitDispSveReg(id->idReg3(), id->idInsOpt(), true); // mmmmm
emitDispSveReg(id->idReg4(), INS_OPTS_SCALABLE_D, false); // nnnnn
emitDispSveReg(id->idReg3(), id->idInsOpt(), true); // nnnnn
emitDispSveReg(id->idReg4(), INS_OPTS_SCALABLE_D, false); // mmmmm
break;

// <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>
case IF_SVE_CY_3A: // ........xx.iiiii ...gggnnnnn.DDDD -- SVE integer compare with signed immediate
case IF_SVE_CY_3B: // ........xx.iiiii ii.gggnnnnn.DDDD -- SVE integer compare with unsigned immediate
emitDispPredicateReg(id->idReg1(), PREDICATE_SIZED, id->idInsOpt(), true); // DDDD
emitDispPredicateReg(id->idReg2(), PREDICATE_ZERO, id->idInsOpt(), true); // ggg
emitDispSveReg(id->idReg3(), id->idInsOpt(), true); // nnnnn
emitDispImm(emitGetInsSC(id), false, (fmt == IF_SVE_CY_3B)); // iiiii
break;

// <Zda>.<T>, <Pg>/M, <Zn>.<Tb>
Expand Down Expand Up @@ -21692,6 +21795,12 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins
result.insThroughput = PERFSCORE_THROUGHPUT_1C;
break;

case IF_SVE_CY_3A: // ........xx.iiiii ...gggnnnnn.DDDD -- SVE integer compare with signed immediate
case IF_SVE_CY_3B: // ........xx.iiiii ii.gggnnnnn.DDDD -- SVE integer compare with unsigned immediate
result.insLatency = PERFSCORE_LATENCY_4C;
result.insThroughput = PERFSCORE_THROUGHPUT_1C;
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
18 changes: 18 additions & 0 deletions src/coreclr/jit/emitarm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,12 @@ static code_t insEncodeSimm4_MultipleOf16_19_to_16(ssize_t imm);
// Returns the encoding for the immediate value that is a multiple of 32 as 4-bits at bit locations '19-16'.
static code_t insEncodeSimm4_MultipleOf32_19_to_16(ssize_t imm);

// Returns the encoding for the immediate value as 5-bits at bit locations '20-16'.
static code_t insEncodeSimm5_20_to_16(ssize_t imm);

// Returns the encoding for the immediate value as 7-bits at bit locations '20-14'.
static code_t insEncodeUimm7_20_to_14(ssize_t imm);

// Returns the encoding to select the elemsize for an Arm64 SVE vector instruction plus an immediate.
// 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);
Expand Down Expand Up @@ -580,6 +586,12 @@ static bool isValidUimm5(ssize_t value)
return (0 <= value) && (value <= 0x1FLL);
};

// Returns true if 'value' is a legal unsigned immediate 7 bit encoding (such as for CMPLT, CMPNE).
static bool isValidUimm7(ssize_t value)
{
return (0 <= value) && (value <= 0x7FLL);
};

// Returns true if 'value' is a legal unsigned immediate 8 bit encoding (such as for FMOV).
static bool isValidUimm8(ssize_t value)
{
Expand Down Expand Up @@ -616,6 +628,12 @@ static bool isValidSimm14(ssize_t value)
return (-0x2000LL <= value) && (value <= 0x1FFFLL);
};

// Returns true if 'value' is a legal signed immediate 5 bit encoding (such as for CMPLO, CMPHI).
static bool isValidSimm5(ssize_t value)
{
return (-0x10LL <= value) && (value <= 0xFLL);
};

// Returns true if 'value' represents a valid 'bitmask immediate' encoding.
static bool isValidImmNRS(size_t value, emitAttr size)
{
Expand Down

0 comments on commit 08cff56

Please sign in to comment.