Skip to content

Add ARM64 encodings for group IF_SVE_GQ_3A #98352

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

Merged
merged 3 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/coreclr/jit/codegenarm64test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5035,6 +5035,18 @@ void CodeGen::genArm64EmitterUnitTestsSve()
theEmitter->emitIns_R_R_R_R(INS_sve_nmatch, EA_SCALABLE, REG_P0, REG_P7, REG_V11, REG_V31,
INS_OPTS_SCALABLE_H); // NMATCH <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>

// IF_SVE_GQ_3A
theEmitter->emitIns_R_R_R(INS_sve_bfcvtnt, EA_SCALABLE, REG_V3, REG_P0, REG_V4); // BFCVTNT <Zd>.H, <Pg>/M, <Zn>.S
theEmitter->emitIns_R_R_R(INS_sve_fcvtlt, EA_SCALABLE, REG_V0, REG_P7, REG_V1,
INS_OPTS_S_TO_D); // FCVTLT <Zd>.D, <Pg>/M, <Zn>.S
theEmitter->emitIns_R_R_R(INS_sve_fcvtlt, EA_SCALABLE, REG_V14, REG_P7, REG_V20,
INS_OPTS_H_TO_S); // FCVTLT <Zd>.S, <Pg>/M, <Zn>.H
theEmitter->emitIns_R_R_R(INS_sve_fcvtnt, EA_SCALABLE, REG_V18, REG_P3, REG_V9,
INS_OPTS_S_TO_H); // FCVTNT <Zd>.H, <Pg>/M, <Zn>.S
theEmitter->emitIns_R_R_R(INS_sve_fcvtnt, EA_SCALABLE, REG_V12, REG_P3, REG_V5,
INS_OPTS_D_TO_S); // FCVTNT <Zd>.S, <Pg>/M, <Zn>.D
theEmitter->emitIns_R_R_R(INS_sve_fcvtxnt, EA_SCALABLE, REG_V1, REG_P2, REG_V3); // FCVTXNT <Zd>.S, <Pg>/M, <Zn>.D

// IF_SVE_GR_3A
theEmitter->emitIns_R_R_R(INS_sve_faddp, EA_SCALABLE, REG_V16, REG_P3, REG_V19,
INS_OPTS_SCALABLE_H); // FADDP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
Expand Down
132 changes: 132 additions & 0 deletions src/coreclr/jit/emitarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1343,6 +1343,25 @@ void emitter::emitInsSanityCheck(instrDesc* id)
assert(isVectorRegister(id->idReg4())); // mmmmm
break;

case IF_SVE_GQ_3A: // ................ ...gggnnnnnddddd -- SVE floating-point convert precision odd elements
switch (id->idIns())
{
case INS_sve_fcvtnt:
case INS_sve_fcvtlt:
assert(insOptsConvertFloatStepwise(id->idInsOpt()));
FALLTHROUGH;
case INS_sve_fcvtxnt:
case INS_sve_bfcvtnt:
assert(isVectorRegister(id->idReg1())); // ddddd
assert(isLowPredicateRegister(id->idReg2())); // ggg
assert(isVectorRegister(id->idReg3())); // nnnnn
break;
default:
assert(!"unreachable");
break;
}
break;

case IF_SVE_HT_4A: // ........xx.mmmmm ...gggnnnnn.DDDD -- SVE floating-point compare vectors
elemsize = id->idOpSize();
assert(isScalableVectorSize(elemsize));
Expand Down Expand Up @@ -6551,6 +6570,53 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt)
return registerListSize;
}

/*****************************************************************************
*
* Expands an option that has different size operands (INS_OPTS_*_TO_*) into
* a pair of scalable options where the first describes the size of the
* destination operand and the second describes the size of the source operand.
*/

/*static*/ void emitter::optExpandConversionPair(insOpts opt, insOpts& dst, insOpts& src)
{
dst = INS_OPTS_NONE;
src = INS_OPTS_NONE;

switch (opt)
{
case INS_OPTS_H_TO_S:
dst = INS_OPTS_SCALABLE_S;
src = INS_OPTS_SCALABLE_H;
break;
case INS_OPTS_S_TO_H:
dst = INS_OPTS_SCALABLE_H;
src = INS_OPTS_SCALABLE_S;
break;
case INS_OPTS_S_TO_D:
dst = INS_OPTS_SCALABLE_D;
src = INS_OPTS_SCALABLE_S;
break;
case INS_OPTS_D_TO_S:
dst = INS_OPTS_SCALABLE_S;
src = INS_OPTS_SCALABLE_D;
break;
case INS_OPTS_H_TO_D:
dst = INS_OPTS_SCALABLE_D;
src = INS_OPTS_SCALABLE_H;
break;
case INS_OPTS_D_TO_H:
dst = INS_OPTS_SCALABLE_H;
src = INS_OPTS_SCALABLE_D;
break;
default:
noway_assert(!"unreachable");
break;
}

assert(dst != INS_OPTS_NONE && src != INS_OPTS_NONE);
return;
}

// For the given 'arrangement' returns the 'datasize' specified by the vector register arrangement
// asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
//
Expand Down Expand Up @@ -10890,6 +10956,18 @@ void emitter::emitIns_R_R_R(instruction ins,
fmt = IF_SVE_EU_3A;
break;

case INS_sve_fcvtnt:
case INS_sve_fcvtlt:
assert(insOptsConvertFloatStepwise(opt));
FALLTHROUGH;
case INS_sve_fcvtxnt:
case INS_sve_bfcvtnt:
assert(isVectorRegister(reg1)); // ddddd
assert(isLowPredicateRegister(reg2)); // ggg
assert(isVectorRegister(reg3)); // nnnnn
fmt = IF_SVE_GQ_3A;
break;

case INS_sve_faddp:
case INS_sve_fmaxnmp:
case INS_sve_fmaxp:
Expand Down Expand Up @@ -21284,6 +21362,24 @@ BYTE* emitter::emitOutput_InstrSve(BYTE* dst, instrDesc* id)
dst += emitOutput_Instr(dst, code);
break;

case IF_SVE_GQ_3A: // ................ ...gggnnnnnddddd -- SVE floating-point convert precision odd elements
code = emitInsCodeSve(ins, fmt);

if (ins == INS_sve_fcvtnt && id->idInsOpt() == INS_OPTS_D_TO_S)
{
code |= (1 << 22 | 1 << 17);
}
else if (ins == INS_sve_fcvtlt && id->idInsOpt() == INS_OPTS_S_TO_D)
{
code |= (1 << 22 | 1 << 17);
}

code |= insEncodeReg_V_4_to_0(id->idReg1()); // ddddd
code |= insEncodeReg_P_12_to_10(id->idReg2()); // ggg
code |= insEncodeReg_V_9_to_5(id->idReg3()); // nnnnn
dst += emitOutput_Instr(dst, code);
break;

// Scalable to general register.
case IF_SVE_CO_3A: // ........xx...... ...gggmmmmmddddd -- SVE conditionally extract element to general register
case IF_SVE_CS_3A: // ........xx...... ...gggnnnnnddddd -- SVE extract element to general register
Expand Down Expand Up @@ -25287,6 +25383,37 @@ void emitter::emitDispInsHelp(
break;
}

// <Zd>.H, <Pg>/M, <Zn>.S
// <Zd>.S, <Pg>/M, <Zn>.D
// <Zd>.D, <Pg>/M, <Zn>.S
// <Zd>.S, <Pg>/M, <Zn>.H
case IF_SVE_GQ_3A: // ................ ...gggnnnnnddddd -- SVE floating-point convert precision odd elements
{
insOpts opt = id->idInsOpt();

switch (ins)
{
// These cases have only one combination of operands so the option may be omitted.
case INS_sve_fcvtxnt:
opt = INS_OPTS_D_TO_S;
break;
case INS_sve_bfcvtnt:
opt = INS_OPTS_S_TO_H;
break;
default:
break;
}

insOpts dst = INS_OPTS_NONE;
insOpts src = INS_OPTS_NONE;
optExpandConversionPair(opt, dst, src);

emitDispSveReg(id->idReg1(), dst, true); // ddddd
emitDispPredicateReg(id->idReg2(), insGetPredicateType(fmt), id->idInsOpt(), true); // ggg
emitDispSveReg(id->idReg3(), src, false); // nnnnn
break;
}

// { <Zt>.D }, <Pg>/Z, [<Xn|SP>{, #<imm>, MUL VL}]
// Some of these formats may allow changing the element size instead of using 'D' for all instructions.
case IF_SVE_IH_3A: // ............iiii ...gggnnnnnttttt -- SVE contiguous load (quadwords, scalar plus
Expand Down Expand Up @@ -28396,6 +28523,11 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins
result.insThroughput = PERFSCORE_THROUGHPUT_1C;
break;

case IF_SVE_GQ_3A: // ................ ...gggnnnnnddddd -- SVE floating-point convert precision odd elements
result.insThroughput = PERFSCORE_THROUGHPUT_1C;
result.insLatency = PERFSCORE_LATENCY_3C;
break;

// Floating point arithmetic
// Floating point min/max pairwise
case IF_SVE_GR_3A: // ........xx...... ...gggmmmmmddddd -- SVE2 floating-point pairwise operations
Expand Down
9 changes: 9 additions & 0 deletions src/coreclr/jit/emitarm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -848,6 +848,10 @@ static insOpts optMakeArrangement(emitAttr datasize, emitAttr elemsize);
// For the given 'datasize' and 'opt' returns true if it specifies a valid vector register arrangement
static bool isValidArrangement(emitAttr datasize, insOpts opt);

// Expands an option that has different size operands (INS_OPTS_*_TO_*) into a pair of scalable options where
// the first describes the size of the destination operand and the second describes the size of the source operand.
static void optExpandConversionPair(insOpts opt, insOpts& dst, insOpts& src);

// For the given 'arrangement' returns the 'datasize' specified by the vector register arrangement
static emitAttr optGetDatasize(insOpts arrangement);

Expand Down Expand Up @@ -1156,6 +1160,11 @@ inline static bool insOptsAnyArrangement(insOpts opt)
return ((opt >= INS_OPTS_8B) && (opt <= INS_OPTS_2D));
}

inline static bool insOptsConvertFloatStepwise(insOpts opt)
{
return (opt == INS_OPTS_H_TO_S || opt == INS_OPTS_S_TO_H || opt == INS_OPTS_D_TO_S || opt == INS_OPTS_S_TO_D);
}

inline static bool insOptsConvertFloatToFloat(insOpts opt)
{
return ((opt >= INS_OPTS_S_TO_D) && (opt <= INS_OPTS_D_TO_H));
Expand Down
8 changes: 4 additions & 4 deletions src/coreclr/jit/instrsarm64sve.h
Original file line number Diff line number Diff line change
Expand Up @@ -1312,8 +1312,8 @@ INST2(pmullt, "pmullt", 0, IF_SV


// enum name info SVE_GQ_3A SVE_HG_2A
INST2(fcvtnt, "fcvtnt", 0, IF_SVE_2BJ, 0x64CAA000, 0x650A3C00 )
// FCVTNT <Zd>.S, <Pg>/M, <Zn>.D SVE_GQ_3A 0110010011001010 101gggnnnnnddddd 64CA A000
INST2(fcvtnt, "fcvtnt", 0, IF_SVE_2BJ, 0x6488A000, 0x650A3C00 )
// FCVTNT <Zd>.H, <Pg>/M, <Zn>.S SVE_GQ_3A 0110010010001000 101gggnnnnnddddd 6488 A000
// FCVTNT <Zd>.B, {<Zn1>.S-<Zn2>.S } SVE_HG_2A 0110010100001010 001111nnnn0ddddd 650A 3C00


Expand Down Expand Up @@ -2669,8 +2669,8 @@ INST1(histcnt, "histcnt", 0, IF_SV
INST1(bfcvtnt, "bfcvtnt", 0, IF_SVE_GQ_3A, 0x648AA000 )
// BFCVTNT <Zd>.H, <Pg>/M, <Zn>.S SVE_GQ_3A 0110010010001010 101gggnnnnnddddd 648A A000

INST1(fcvtlt, "fcvtlt", 0, IF_SVE_GQ_3A, 0x64CBA000 )
// FCVTLT <Zd>.D, <Pg>/M, <Zn>.S SVE_GQ_3A 0110010011001011 101gggnnnnnddddd 64CB A000
INST1(fcvtlt, "fcvtlt", 0, IF_SVE_GQ_3A, 0x6489A000 )
// FCVTLT <Zd>.S, <Pg>/M, <Zn>.H SVE_GQ_3A 0110010010001001 101gggnnnnnddddd 6489 A000

INST1(fcvtxnt, "fcvtxnt", 0, IF_SVE_GQ_3A, 0x640AA000 )
// FCVTXNT <Zd>.S, <Pg>/M, <Zn>.D SVE_GQ_3A 0110010000001010 101gggnnnnnddddd 640A A000
Expand Down