diff --git a/src/coreclr/jit/codegeninterface.h b/src/coreclr/jit/codegeninterface.h index ac27efaeb9b3cb..645948206d672f 100644 --- a/src/coreclr/jit/codegeninterface.h +++ b/src/coreclr/jit/codegeninterface.h @@ -185,6 +185,8 @@ class CodeGenInterface static unsigned instInputSize(instruction ins); static unsigned instKMaskBaseSize(instruction ins); + static bool instHasPseudoName(instruction ins); + bool IsEmbeddedBroadcastEnabled(instruction ins, GenTree* op); #endif // TARGET_XARCH //------------------------------------------------------------------------- diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp index aadf62d20de21d..696ae2c34ca7f3 100644 --- a/src/coreclr/jit/emitxarch.cpp +++ b/src/coreclr/jit/emitxarch.cpp @@ -12559,13 +12559,25 @@ void emitter::emitDispConstant(const instrDesc* id, bool skipComma) const { instruction ins = id->idIns(); - if ((ins == INS_cmppd) || (ins == INS_cmpps) || (ins == INS_cmpsd) || (ins == INS_cmpss) || - (ins == INS_pclmulqdq) || (ins == INS_vpcmpb) || (ins == INS_vpcmpd) || (ins == INS_vpcmpq) || - (ins == INS_vpcmpw) || (ins == INS_vpcmpub) || (ins == INS_vpcmpud) || (ins == INS_vpcmpuq) || - (ins == INS_vpcmpuw)) + if (CodeGenInterface::instHasPseudoName(ins)) { - // These instructions have pseudo-names for each possible immediate value - return; + switch (ins) + { + case INS_roundpd: + case INS_roundps: + case INS_roundsd: + case INS_roundss: + { + // These instructions have pseudo-names, but still need to display the immediate + break; + } + + default: + { + // These instructions have pseudo-names for each possible immediate value + return; + } + } } CnsVal cnsVal; diff --git a/src/coreclr/jit/instr.cpp b/src/coreclr/jit/instr.cpp index 6dde8786295a6f..c336b1c521d03a 100644 --- a/src/coreclr/jit/instr.cpp +++ b/src/coreclr/jit/instr.cpp @@ -116,20 +116,33 @@ const char* CodeGen::genInsDisplayName(emitter::instrDesc* id) const emitter* emit = GetEmitter(); const char* vexPrefix = emit->UseVEXEncoding() ? "v" : ""; - auto AddPrefixAndSuffix = [&](const char* prefix, const char* insName, const char* suffix1, - const char* suffix2) -> const char* { + auto AddSuffix = [&](const char* insName, const char* suffix1, const char* suffix2 = "") -> const char* { const int TEMP_BUFFER_LEN = 40; static unsigned curBuf = 0; static char buf[4][TEMP_BUFFER_LEN]; const char* retbuf; - sprintf_s(buf[curBuf], TEMP_BUFFER_LEN, "%s%s%s%s", prefix, insName, suffix1, suffix2); + sprintf_s(buf[curBuf], TEMP_BUFFER_LEN, "%s%s%s", insName, suffix1, suffix2); retbuf = buf[curBuf]; curBuf = (curBuf + 1) % 4; return retbuf; }; - auto GetFltCmpOpName = [&](emitter::instrDesc* id, const char* suffix) -> const char* { + auto RemoveVexPrefixIfNeeded = [&](const char* insName) -> const char* { + if (emit->UseVEXEncoding()) + { + return insName; + } + + if (insName[0] == 'v') + { + return insName + 1; + } + + return insName; + }; + + auto GetFltCmpOpName = [&](const char* suffix) -> const char* { static const char* const fltCmpOpNames[] = { "eq", "lt", "le", "unord", "neq", "nlt", "nle", "ord", "eq_uq", "nge", "ngt", "false", "neq_oq", "ge", "gt", "true", @@ -141,10 +154,10 @@ const char* CodeGen::genInsDisplayName(emitter::instrDesc* id) assert(control < ArrLen(fltCmpOpNames)); const char* pseudoName = fltCmpOpNames[control]; - return AddPrefixAndSuffix(vexPrefix, "cmp", pseudoName, suffix); + return RemoveVexPrefixIfNeeded(AddSuffix("vcmp", pseudoName, suffix)); }; - auto GetIntCmpOpName = [&](emitter::instrDesc* id, const char* suffix) -> const char* { + auto GetIntCmpOpName = [&](const char* suffix) -> const char* { static const char* const intCmpOpNames[] = { "eq", "lt", "le", "neq", "false", "ge", "gt", "true", }; @@ -153,237 +166,260 @@ const char* CodeGen::genInsDisplayName(emitter::instrDesc* id) assert(control < ArrLen(intCmpOpNames)); const char* pseudoName = intCmpOpNames[control]; - return AddPrefixAndSuffix(vexPrefix, "pcmp", pseudoName, suffix); + return RemoveVexPrefixIfNeeded(AddSuffix("vpcmp", pseudoName, suffix)); }; - // Some instructions have different mnemonics depending on the immediate. - switch (ins) - { - case INS_cmppd: + auto GetEvexOnlyName = [&](const char* pseudoName) -> const char* { + if (emit->TakesEvexPrefix(id)) { - return GetFltCmpOpName(id, "pd"); + return pseudoName; } + return RemoveVexPrefixIfNeeded(insName); + }; - case INS_cmpps: - { - return GetFltCmpOpName(id, "ps"); - } + if (instHasPseudoName(ins)) + { + // Some instructions have different mnemonics available - case INS_cmpsd: + switch (ins) { - return GetFltCmpOpName(id, "sd"); - } + case INS_cdq: + { + switch (id->idOpSize()) + { + case EA_8BYTE: + { + return "cqo"; + } - case INS_cmpss: - { - return GetFltCmpOpName(id, "ss"); - } + case EA_4BYTE: + { + return "cdq"; + } - case INS_pclmulqdq: - { - uint8_t control = static_cast(emit->emitGetInsSC(id)) & 0x11; + case EA_2BYTE: + { + return "cwd"; + } - if (control == 0x00) - { - insName = "lqlq"; + default: + { + unreached(); + } + } + break; } - else if (control == 0x01) + + case INS_cmppd: + case INS_vcmppd: { - insName = "hqlq"; + return GetFltCmpOpName("pd"); } - else if (control == 0x10) + + case INS_cmpps: + case INS_vcmpps: { - insName = "lqhq"; + return GetFltCmpOpName("ps"); } - else + + case INS_cmpsd: + case INS_vcmpsd: { - insName = "hqhq"; + return GetFltCmpOpName("sd"); } - return AddPrefixAndSuffix(vexPrefix, "pclmul", insName, "dq"); - } - - case INS_vpcmpb: - { - return GetIntCmpOpName(id, "b"); - } - - case INS_vpcmpd: - { - return GetIntCmpOpName(id, "d"); - } - - case INS_vpcmpq: - { - return GetIntCmpOpName(id, "q"); - } - - case INS_vpcmpub: - { - return GetIntCmpOpName(id, "ub"); - } - - case INS_vpcmpud: - { - return GetIntCmpOpName(id, "ud"); - } - - case INS_vpcmpuq: - { - return GetIntCmpOpName(id, "uq"); - } - - case INS_vpcmpuw: - { - return GetIntCmpOpName(id, "uw"); - } - - case INS_vpcmpw: - { - return GetIntCmpOpName(id, "w"); - } - - default: - { - break; - } - } - - if (id->idIsApxPpxContextSet()) - { - return AddPrefixAndSuffix("", insName, "p", ""); - } + case INS_cmpss: + case INS_vcmpss: + { + return GetFltCmpOpName("ss"); + } - if (emit->IsVexOrEvexEncodableInstruction(ins)) - { - if (!emit->IsBMIInstruction(ins) && !emit->IsKInstruction(ins)) - { - if (emit->TakesEvexPrefix(id)) + case INS_cwde: { - switch (ins) + switch (id->idOpSize()) { - case INS_movdqa32: + case EA_8BYTE: { - return "vmovdqa32"; + return "cdqe"; } - case INS_movdqu32: + case EA_4BYTE: { - return "vmovdqu32"; + return "cwde"; } - case INS_pandd: + case EA_2BYTE: { - return "vpandd"; + return "cbw"; } - case INS_pandnd: + default: { - return "vpandnd"; + unreached(); } + } + } - case INS_pord: - { - return "vpord"; - } + case INS_movdqa32: + { + return GetEvexOnlyName("vmovdqa32"); + } - case INS_pxord: - { - return "vpxord"; - } + case INS_movdqu32: + { + return GetEvexOnlyName("vmovdqu32"); + } - case INS_roundpd: - { - return "vrndscalepd"; - } + case INS_pandd: + { + return GetEvexOnlyName("vpandd"); + } - case INS_roundps: - { - return "vrndscaleps"; - } + case INS_pandnd: + { + return GetEvexOnlyName("vpandnd"); + } - case INS_roundsd: + case INS_pclmulqdq: + { + switch (static_cast(emit->emitGetInsSC(id)) & 0x11) + { + case 0x00: { - return "vrndscalesd"; + return RemoveVexPrefixIfNeeded("vpclmullqlqdq"); } - case INS_roundss: + case 0x01: { - return "vrndscaless"; + return RemoveVexPrefixIfNeeded("vpclmulhqlqdq"); } - case INS_vbroadcastf32x4: + case 0x10: { - return "vbroadcastf32x4"; + return RemoveVexPrefixIfNeeded("vpclmullqhqdq"); } - case INS_vextractf32x4: + default: { - return "vextractf32x4"; + return RemoveVexPrefixIfNeeded("vpclmulhqhqdq"); } + } + } - case INS_vinsertf32x4: - { - return "vinsertf32x4"; - } + case INS_pord: + { + return GetEvexOnlyName("vpord"); + } - case INS_vbroadcasti32x4: - { - return "vbroadcasti32x4"; - } + case INS_pxord: + { + return GetEvexOnlyName("vpxord"); + } - case INS_vextracti32x4: - { - return "vextracti32x4"; - } + case INS_roundpd: + { + return GetEvexOnlyName("vrndscalepd"); + } - case INS_vinserti32x4: - { - return "vinserti32x4"; - } + case INS_roundps: + { + return GetEvexOnlyName("vrndscaleps"); + } - default: - { - break; - } - } + case INS_roundsd: + { + return GetEvexOnlyName("vrndscalesd"); } - return AddPrefixAndSuffix("v", insName, "", ""); - } - } + case INS_roundss: + { + return GetEvexOnlyName("vrndscaless"); + } - // Some instructions have different mnemonics depending on the size. - switch (ins) - { - case INS_cdq: - switch (id->idOpSize()) + case INS_vbroadcastf32x4: { - case EA_8BYTE: - return "cqo"; - case EA_4BYTE: - return "cdq"; - case EA_2BYTE: - return "cwd"; - default: - unreached(); + return GetEvexOnlyName("vbroadcastf32x4"); } - case INS_cwde: - switch (id->idOpSize()) + case INS_vbroadcasti32x4: { - case EA_8BYTE: - return "cdqe"; - case EA_4BYTE: - return "cwde"; - case EA_2BYTE: - return "cbw"; - default: - unreached(); + return GetEvexOnlyName("vbroadcasti32x4"); } - default: - break; + case INS_vextractf32x4: + { + return GetEvexOnlyName("vextractf32x4"); + } + + case INS_vextracti32x4: + { + return GetEvexOnlyName("vextracti32x4"); + } + + case INS_vinsertf32x4: + { + return GetEvexOnlyName("vinsertf32x4"); + } + + case INS_vinserti32x4: + { + return GetEvexOnlyName("vinserti32x4"); + } + + case INS_vpcmpb: + { + return GetIntCmpOpName("b"); + } + + case INS_vpcmpd: + { + return GetIntCmpOpName("d"); + } + + case INS_vpcmpq: + { + return GetIntCmpOpName("q"); + } + + case INS_vpcmpub: + { + return GetIntCmpOpName("ub"); + } + + case INS_vpcmpud: + { + return GetIntCmpOpName("ud"); + } + + case INS_vpcmpuq: + { + return GetIntCmpOpName("uq"); + } + + case INS_vpcmpuw: + { + return GetIntCmpOpName("uw"); + } + + case INS_vpcmpw: + { + return GetIntCmpOpName("w"); + } + + default: + { + unreached(); + } + } + } + + if (IsSimdInstruction(ins)) + { + return RemoveVexPrefixIfNeeded(insName); + } + else if (id->idIsApxPpxContextSet()) + { + return AddSuffix(insName, "p"); } #endif // TARGET_XARCH @@ -558,6 +594,17 @@ unsigned CodeGenInterface::instKMaskBaseSize(instruction ins) return 0; } } + +/***************************************************************************** + * + * Returns true if the given CPU instruction has a pseudo name + */ + +bool CodeGenInterface::instHasPseudoName(instruction ins) +{ + assert((unsigned)ins < ArrLen(instInfo)); + return (instInfo[ins] & INS_FLAGS_HasPseudoName) != 0; +} #endif // TARGET_XARCH /***************************************************************************** diff --git a/src/coreclr/jit/instr.h b/src/coreclr/jit/instr.h index 2c4ae7ba21ad44..d3a5b5385a3e9d 100644 --- a/src/coreclr/jit/instr.h +++ b/src/coreclr/jit/instr.h @@ -236,6 +236,9 @@ enum insFlags : uint64_t KMask_Base16 = 1ULL << 51, KMask_BaseMask = (0x1FULL) << 47, + // The instruction has a pseudo name that should be used for disasm display + INS_FLAGS_HasPseudoName = 1ULL << 52, + // TODO-Cleanup: Remove this flag and its usage from TARGET_XARCH INS_FLAGS_DONT_CARE = 0x00ULL, };