Skip to content

Commit 08cff56

Browse files
Add Arm64 encodings for IF_SVE_CY_3A and IF_SVE_CY_3B group (#96992)
* Add Arm64 encodings for IF_SVE_CY_3A and IF_SVE_CY_3B group * Fix function declaration --------- Co-authored-by: Kunal Pathak <[email protected]>
1 parent 3ffa1a9 commit 08cff56

File tree

3 files changed

+155
-4
lines changed

3 files changed

+155
-4
lines changed

src/coreclr/jit/codegenarm64test.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4794,6 +4794,30 @@ void CodeGen::genArm64EmitterUnitTestsSve()
47944794
theEmitter->emitIns_R_R_R_R(INS_sve_cmpne, EA_SCALABLE, REG_P0, REG_P0, REG_V14, REG_V28, INS_OPTS_SCALABLE_B,
47954795
INS_SCALABLE_OPTS_WIDE); /* CMPNE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.D */
47964796

4797+
// IF_SVE_CY_3A
4798+
theEmitter->emitIns_R_R_R_I(INS_sve_cmpeq, EA_SCALABLE, REG_P15, REG_P0, REG_V31, 8,
4799+
INS_OPTS_SCALABLE_B); /* CMPEQ <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm> */
4800+
theEmitter->emitIns_R_R_R_I(INS_sve_cmpge, EA_SCALABLE, REG_P11, REG_P7, REG_V21, 1,
4801+
INS_OPTS_SCALABLE_H); /* CMPGE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm> */
4802+
theEmitter->emitIns_R_R_R_I(INS_sve_cmpgt, EA_SCALABLE, REG_P10, REG_P1, REG_V18, 4,
4803+
INS_OPTS_SCALABLE_S); /* CMPGT <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm> */
4804+
theEmitter->emitIns_R_R_R_I(INS_sve_cmple, EA_SCALABLE, REG_P8, REG_P6, REG_V11, 15,
4805+
INS_OPTS_SCALABLE_D); /* CMPLE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm> */
4806+
theEmitter->emitIns_R_R_R_I(INS_sve_cmplt, EA_SCALABLE, REG_P7, REG_P2, REG_V8, -16,
4807+
INS_OPTS_SCALABLE_B); /* CMPLT <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm> */
4808+
theEmitter->emitIns_R_R_R_I(INS_sve_cmpne, EA_SCALABLE, REG_P0, REG_P5, REG_V0, -14,
4809+
INS_OPTS_SCALABLE_H); /* CMPNE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm> */
4810+
4811+
// IF_SVE_CY_3B
4812+
theEmitter->emitIns_R_R_R_I(INS_sve_cmphi, EA_SCALABLE, REG_P15, REG_P7, REG_V19, 0,
4813+
INS_OPTS_SCALABLE_B); /* CMPHI <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm> */
4814+
theEmitter->emitIns_R_R_R_I(INS_sve_cmphs, EA_SCALABLE, REG_P11, REG_P1, REG_V0, 36,
4815+
INS_OPTS_SCALABLE_H); /* CMPHS <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm> */
4816+
theEmitter->emitIns_R_R_R_I(INS_sve_cmplo, EA_SCALABLE, REG_P8, REG_P5, REG_V21, 64,
4817+
INS_OPTS_SCALABLE_S); /* CMPLO <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm> */
4818+
theEmitter->emitIns_R_R_R_I(INS_sve_cmpls, EA_SCALABLE, REG_P0, REG_P3, REG_V9, 127,
4819+
INS_OPTS_SCALABLE_D); /* CMPLS <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm> */
4820+
47974821
// IF_SVE_EP_3A
47984822
theEmitter->emitIns_R_R_R(INS_sve_shadd, EA_SCALABLE, REG_V15, REG_P0, REG_V10,
47994823
INS_OPTS_SCALABLE_B); // SHADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>

src/coreclr/jit/emitarm64.cpp

Lines changed: 113 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,8 +1072,28 @@ void emitter::emitInsSanityCheck(instrDesc* id)
10721072
assert(insOptsScalableWide(id->idInsOpt())); // xx
10731073
assert(isPredicateRegister(id->idReg1())); // DDDD
10741074
assert(isLowPredicateRegister(id->idReg2())); // ggg
1075-
assert(isVectorRegister(id->idReg3())); // mmmmm
1076-
assert(isVectorRegister(id->idReg4())); // nnnnn
1075+
assert(isVectorRegister(id->idReg3())); // nnnnn
1076+
assert(isVectorRegister(id->idReg4())); // mmmmm
1077+
break;
1078+
1079+
case IF_SVE_CY_3A: // ........xx.iiiii ...gggnnnnn.DDDD -- SVE integer compare with signed immediate
1080+
elemsize = id->idOpSize();
1081+
assert(isScalableVectorSize(elemsize));
1082+
assert(insOptsScalableStandard(id->idInsOpt()));
1083+
assert(isPredicateRegister(id->idReg1())); // DDDD
1084+
assert(isLowPredicateRegister(id->idReg2())); // ggg
1085+
assert(isVectorRegister(id->idReg3())); // nnnnn
1086+
assert(isValidSimm5(emitGetInsSC(id))); // iiiii
1087+
break;
1088+
1089+
case IF_SVE_CY_3B: // ........xx.iiiii ii.gggnnnnn.DDDD -- SVE integer compare with unsigned immediate
1090+
elemsize = id->idOpSize();
1091+
assert(isScalableVectorSize(elemsize));
1092+
assert(insOptsScalableStandard(id->idInsOpt()));
1093+
assert(isPredicateRegister(id->idReg1())); // DDDD
1094+
assert(isLowPredicateRegister(id->idReg2())); // ggg
1095+
assert(isVectorRegister(id->idReg3())); // nnnnn
1096+
assert(isValidUimm7(emitGetInsSC(id))); // iiiii
10771097
break;
10781098

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

9662+
case INS_sve_cmpeq:
9663+
case INS_sve_cmpgt:
9664+
case INS_sve_cmpge:
9665+
case INS_sve_cmpne:
9666+
case INS_sve_cmple:
9667+
case INS_sve_cmplt:
9668+
assert(insOptsScalableStandard(opt));
9669+
assert(isPredicateRegister(reg1)); // DDDD
9670+
assert(isLowPredicateRegister(reg2)); // ggg
9671+
assert(isVectorRegister(reg3)); // nnnnn
9672+
assert(isValidSimm5(imm)); // iiiii
9673+
fmt = IF_SVE_CY_3A;
9674+
break;
9675+
9676+
case INS_sve_cmphi:
9677+
case INS_sve_cmphs:
9678+
case INS_sve_cmplo:
9679+
case INS_sve_cmpls:
9680+
assert(insOptsScalableStandard(opt));
9681+
assert(isPredicateRegister(reg1)); // DDDD
9682+
assert(isLowPredicateRegister(reg2)); // ggg
9683+
assert(isVectorRegister(reg3)); // nnnnn
9684+
assert(isValidUimm7(imm)); // iiiii
9685+
fmt = IF_SVE_CY_3B;
9686+
break;
9687+
96429688
case INS_fmul: // by element, imm[0..3] selects the element of reg3
96439689
case INS_fmla:
96449690
case INS_fmls:
@@ -14348,6 +14394,32 @@ void emitter::emitIns_Call(EmitCallType callType,
1434814394
return insEncodeSimm4_19_to_16(imm / 32);
1434914395
}
1435014396

14397+
/*****************************************************************************
14398+
*
14399+
* Returns the encoding for the immediate value as 5-bits at bit locations '20-16'.
14400+
*/
14401+
14402+
/*static*/ emitter::code_t emitter::insEncodeSimm5_20_to_16(ssize_t imm)
14403+
{
14404+
assert(isValidSimm5(imm));
14405+
if (imm < 0)
14406+
{
14407+
imm = (imm & 0x1F);
14408+
}
14409+
return (code_t)imm << 16;
14410+
}
14411+
14412+
/*****************************************************************************
14413+
*
14414+
* Returns the encoding for the immediate value as 7-bits at bit locations '20-14'.
14415+
*/
14416+
14417+
/*static*/ emitter::code_t emitter::insEncodeUimm7_20_to_14(ssize_t imm)
14418+
{
14419+
assert(isValidUimm7(imm));
14420+
return (code_t)imm << 14;
14421+
}
14422+
1435114423
/*****************************************************************************
1435214424
*
1435314425
* Returns the encoding to select the <R> 4/8-byte width specifier <R>
@@ -16439,6 +16511,28 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
1643916511
dst += emitOutput_Instr(dst, code);
1644016512
break;
1644116513

16514+
case IF_SVE_CY_3A: // ........xx.iiiii ...gggnnnnn.DDDD -- SVE integer compare with signed immediate
16515+
imm = emitGetInsSC(id);
16516+
code = emitInsCodeSve(ins, fmt);
16517+
code |= insEncodeReg_P_3_to_0(id->idReg1()); // DDDD
16518+
code |= insEncodeReg_P_12_to_10(id->idReg2()); // ggg
16519+
code |= insEncodeReg_V_9_to_5(id->idReg3()); // nnnnn
16520+
code |= insEncodeSimm5_20_to_16(imm); // iiiii
16521+
code |= insEncodeElemsize(optGetSveElemsize(id->idInsOpt())); // xx
16522+
dst += emitOutput_Instr(dst, code);
16523+
break;
16524+
16525+
case IF_SVE_CY_3B: // ........xx.iiiii ii.gggnnnnn.DDDD -- SVE integer compare with unsigned immediate
16526+
imm = emitGetInsSC(id);
16527+
code = emitInsCodeSve(ins, fmt);
16528+
code |= insEncodeReg_P_3_to_0(id->idReg1()); // DDDD
16529+
code |= insEncodeReg_P_12_to_10(id->idReg2()); // ggg
16530+
code |= insEncodeReg_V_9_to_5(id->idReg3()); // nnnnn
16531+
code |= insEncodeUimm7_20_to_14(imm); // iiiii
16532+
code |= insEncodeElemsize(optGetSveElemsize(id->idInsOpt())); // xx
16533+
dst += emitOutput_Instr(dst, code);
16534+
break;
16535+
1644216536
case IF_SVE_GA_2A: // ............iiii ......nnnn.ddddd -- SME2 multi-vec shift narrow
1644316537
imm = emitGetInsSC(id);
1644416538
assert(id->idInsOpt() == INS_OPTS_SCALABLE_H);
@@ -19109,8 +19203,17 @@ void emitter::emitDispInsHelp(
1910919203
case IF_SVE_CX_4A_A: // ........xx.mmmmm ...gggnnnnn.DDDD -- SVE integer compare vectors
1911019204
emitDispPredicateReg(id->idReg1(), PREDICATE_SIZED, id->idInsOpt(), true); // DDDD
1911119205
emitDispPredicateReg(id->idReg2(), PREDICATE_ZERO, id->idInsOpt(), true); // ggg
19112-
emitDispSveReg(id->idReg3(), id->idInsOpt(), true); // mmmmm
19113-
emitDispSveReg(id->idReg4(), INS_OPTS_SCALABLE_D, false); // nnnnn
19206+
emitDispSveReg(id->idReg3(), id->idInsOpt(), true); // nnnnn
19207+
emitDispSveReg(id->idReg4(), INS_OPTS_SCALABLE_D, false); // mmmmm
19208+
break;
19209+
19210+
// <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>
19211+
case IF_SVE_CY_3A: // ........xx.iiiii ...gggnnnnn.DDDD -- SVE integer compare with signed immediate
19212+
case IF_SVE_CY_3B: // ........xx.iiiii ii.gggnnnnn.DDDD -- SVE integer compare with unsigned immediate
19213+
emitDispPredicateReg(id->idReg1(), PREDICATE_SIZED, id->idInsOpt(), true); // DDDD
19214+
emitDispPredicateReg(id->idReg2(), PREDICATE_ZERO, id->idInsOpt(), true); // ggg
19215+
emitDispSveReg(id->idReg3(), id->idInsOpt(), true); // nnnnn
19216+
emitDispImm(emitGetInsSC(id), false, (fmt == IF_SVE_CY_3B)); // iiiii
1911419217
break;
1911519218

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

21798+
case IF_SVE_CY_3A: // ........xx.iiiii ...gggnnnnn.DDDD -- SVE integer compare with signed immediate
21799+
case IF_SVE_CY_3B: // ........xx.iiiii ii.gggnnnnn.DDDD -- SVE integer compare with unsigned immediate
21800+
result.insLatency = PERFSCORE_LATENCY_4C;
21801+
result.insThroughput = PERFSCORE_THROUGHPUT_1C;
21802+
break;
21803+
2169521804
case IF_SVE_GE_4A: // ........xx.mmmmm ...gggnnnnn.DDDD -- SVE2 character match
2169621805
case IF_SVE_HT_4A: // ........xx.mmmmm ...gggnnnnn.DDDD -- SVE floating-point compare vectors
2169721806
result.insLatency = PERFSCORE_LATENCY_2C;

src/coreclr/jit/emitarm64.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,12 @@ static code_t insEncodeSimm4_MultipleOf16_19_to_16(ssize_t imm);
518518
// Returns the encoding for the immediate value that is a multiple of 32 as 4-bits at bit locations '19-16'.
519519
static code_t insEncodeSimm4_MultipleOf32_19_to_16(ssize_t imm);
520520

521+
// Returns the encoding for the immediate value as 5-bits at bit locations '20-16'.
522+
static code_t insEncodeSimm5_20_to_16(ssize_t imm);
523+
524+
// Returns the encoding for the immediate value as 7-bits at bit locations '20-14'.
525+
static code_t insEncodeUimm7_20_to_14(ssize_t imm);
526+
521527
// Returns the encoding to select the elemsize for an Arm64 SVE vector instruction plus an immediate.
522528
// This specifically encodes the field 'tszh:tszl' at bit locations '23-22:9-8'.
523529
static code_t insEncodeSveShift_23_to_22_9_to_0(emitAttr size, bool isRightShift, size_t imm);
@@ -580,6 +586,12 @@ static bool isValidUimm5(ssize_t value)
580586
return (0 <= value) && (value <= 0x1FLL);
581587
};
582588

589+
// Returns true if 'value' is a legal unsigned immediate 7 bit encoding (such as for CMPLT, CMPNE).
590+
static bool isValidUimm7(ssize_t value)
591+
{
592+
return (0 <= value) && (value <= 0x7FLL);
593+
};
594+
583595
// Returns true if 'value' is a legal unsigned immediate 8 bit encoding (such as for FMOV).
584596
static bool isValidUimm8(ssize_t value)
585597
{
@@ -616,6 +628,12 @@ static bool isValidSimm14(ssize_t value)
616628
return (-0x2000LL <= value) && (value <= 0x1FFFLL);
617629
};
618630

631+
// Returns true if 'value' is a legal signed immediate 5 bit encoding (such as for CMPLO, CMPHI).
632+
static bool isValidSimm5(ssize_t value)
633+
{
634+
return (-0x10LL <= value) && (value <= 0xFLL);
635+
};
636+
619637
// Returns true if 'value' represents a valid 'bitmask immediate' encoding.
620638
static bool isValidImmNRS(size_t value, emitAttr size)
621639
{

0 commit comments

Comments
 (0)