From e4cc3744882b4a35a3ae536d7d90a691afca8a65 Mon Sep 17 00:00:00 2001 From: Swapnil Gaikwad Date: Wed, 3 Jan 2024 15:13:07 +0000 Subject: [PATCH 1/2] Add Arm64 encodings for IF_SVE_CY_3A and IF_SVE_CY_3B group --- src/coreclr/jit/codegenarm64test.cpp | 24 ++++++ src/coreclr/jit/emitarm64.cpp | 117 ++++++++++++++++++++++++++- src/coreclr/jit/emitarm64.h | 18 +++++ 3 files changed, 155 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/codegenarm64test.cpp b/src/coreclr/jit/codegenarm64test.cpp index 4cbbaebfa0e3b..0da96d48e22a0 100644 --- a/src/coreclr/jit/codegenarm64test.cpp +++ b/src/coreclr/jit/codegenarm64test.cpp @@ -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 ., /Z, ., .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 ., /Z, ., # */ + theEmitter->emitIns_R_R_R_I(INS_sve_cmpge, EA_SCALABLE, REG_P11, REG_P7, REG_V21, 1, + INS_OPTS_SCALABLE_H); /* CMPGE ., /Z, ., # */ + theEmitter->emitIns_R_R_R_I(INS_sve_cmpgt, EA_SCALABLE, REG_P10, REG_P1, REG_V18, 4, + INS_OPTS_SCALABLE_S); /* CMPGT ., /Z, ., # */ + theEmitter->emitIns_R_R_R_I(INS_sve_cmple, EA_SCALABLE, REG_P8, REG_P6, REG_V11, 15, + INS_OPTS_SCALABLE_D); /* CMPLE ., /Z, ., # */ + theEmitter->emitIns_R_R_R_I(INS_sve_cmplt, EA_SCALABLE, REG_P7, REG_P2, REG_V8, -16, + INS_OPTS_SCALABLE_B); /* CMPLT ., /Z, ., # */ + theEmitter->emitIns_R_R_R_I(INS_sve_cmpne, EA_SCALABLE, REG_P0, REG_P5, REG_V0, -14, + INS_OPTS_SCALABLE_H); /* CMPNE ., /Z, ., # */ + + // 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 ., /Z, ., # */ + theEmitter->emitIns_R_R_R_I(INS_sve_cmphs, EA_SCALABLE, REG_P11, REG_P1, REG_V0, 36, + INS_OPTS_SCALABLE_H); /* CMPHS ., /Z, ., # */ + theEmitter->emitIns_R_R_R_I(INS_sve_cmplo, EA_SCALABLE, REG_P8, REG_P5, REG_V21, 64, + INS_OPTS_SCALABLE_S); /* CMPLO ., /Z, ., # */ + theEmitter->emitIns_R_R_R_I(INS_sve_cmpls, EA_SCALABLE, REG_P0, REG_P3, REG_V9, 127, + INS_OPTS_SCALABLE_D); /* CMPLS ., /Z, ., # */ + // 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 ., /M, ., . diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp index 0de5ebbfdcd73..563218bdc5e6e 100644 --- a/src/coreclr/jit/emitarm64.cpp +++ b/src/coreclr/jit/emitarm64.cpp @@ -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 @@ -9498,6 +9518,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: @@ -14180,6 +14226,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 4/8-byte width specifier @@ -16271,6 +16343,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); @@ -18844,8 +18938,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; + + // ., /Z, ., # + 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; // ., /M, . @@ -21382,6 +21485,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; diff --git a/src/coreclr/jit/emitarm64.h b/src/coreclr/jit/emitarm64.h index b69d71eff8342..63d9d8afc0393 100644 --- a/src/coreclr/jit/emitarm64.h +++ b/src/coreclr/jit/emitarm64.h @@ -513,6 +513,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 emitter::code_t emitter::insEncodeSimm5_20_to_16(ssize_t imm); + +// 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); + // 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); @@ -575,6 +581,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) { @@ -611,6 +623,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) { From cd6f1d140fdd7c22a4063cb9a5910fd61f66293a Mon Sep 17 00:00:00 2001 From: Swapnil Gaikwad Date: Tue, 16 Jan 2024 12:17:39 +0000 Subject: [PATCH 2/2] Fix function declaration --- src/coreclr/jit/emitarm64.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/emitarm64.h b/src/coreclr/jit/emitarm64.h index 63d9d8afc0393..2810935d51c61 100644 --- a/src/coreclr/jit/emitarm64.h +++ b/src/coreclr/jit/emitarm64.h @@ -514,10 +514,10 @@ static code_t insEncodeSimm4_MultipleOf16_19_to_16(ssize_t imm); 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 emitter::code_t emitter::insEncodeSimm5_20_to_16(ssize_t imm); +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 emitter::code_t emitter::insEncodeUimm7_20_to_14(ssize_t imm); +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'.