forked from OSchip/llvm-project
[X86][NFC] Adding one flag to imply whether the instruction should check the predicate when compress EVEX instructions to VEX encoding.
Some EVEX instructions should check the predicates when compress to VEX encoding. For example, avx512vnni instructions. This is because avx512vnni doesn't mean that avxvnni is supported on the target. This patch moving the manually added check to .inc that generated by tablegen. Differential Revision: https://reviews.llvm.org/D98011
This commit is contained in:
parent
0875c2f7f6
commit
3618b21298
|
@ -151,24 +151,6 @@ static bool performCustomAdjustments(MachineInstr &MI, unsigned NewOpc,
|
|||
(void)NewOpc;
|
||||
unsigned Opc = MI.getOpcode();
|
||||
switch (Opc) {
|
||||
case X86::VPDPBUSDSZ256m:
|
||||
case X86::VPDPBUSDSZ256r:
|
||||
case X86::VPDPBUSDSZ128m:
|
||||
case X86::VPDPBUSDSZ128r:
|
||||
case X86::VPDPBUSDZ256m:
|
||||
case X86::VPDPBUSDZ256r:
|
||||
case X86::VPDPBUSDZ128m:
|
||||
case X86::VPDPBUSDZ128r:
|
||||
case X86::VPDPWSSDSZ256m:
|
||||
case X86::VPDPWSSDSZ256r:
|
||||
case X86::VPDPWSSDSZ128m:
|
||||
case X86::VPDPWSSDSZ128r:
|
||||
case X86::VPDPWSSDZ256m:
|
||||
case X86::VPDPWSSDZ256r:
|
||||
case X86::VPDPWSSDZ128m:
|
||||
case X86::VPDPWSSDZ128r:
|
||||
// These can only VEX convert if AVXVNNI is enabled.
|
||||
return ST->hasAVXVNNI();
|
||||
case X86::VALIGNDZ128rri:
|
||||
case X86::VALIGNDZ128rmi:
|
||||
case X86::VALIGNQZ128rri:
|
||||
|
@ -280,6 +262,9 @@ bool EvexToVexInstPass::CompressEvexToVexImpl(MachineInstr &MI) const {
|
|||
if (usesExtendedRegister(MI))
|
||||
return false;
|
||||
|
||||
if (!CheckVEXInstPredicate(MI, ST))
|
||||
return false;
|
||||
|
||||
if (!performCustomAdjustments(MI, NewOpc, ST))
|
||||
return false;
|
||||
|
||||
|
|
|
@ -352,7 +352,8 @@ class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
|
|||
bit isMemoryFoldable = 1; // Is it allowed to memory fold/unfold this instruction?
|
||||
bit notEVEX2VEXConvertible = 0; // Prevent EVEX->VEX conversion.
|
||||
bit ExplicitVEXPrefix = 0; // Force the instruction to use VEX encoding.
|
||||
|
||||
// Force to check predicate before compress EVEX to VEX encoding.
|
||||
bit checkVEXPredicate = 0;
|
||||
// TSFlags layout should be kept in sync with X86BaseInfo.h.
|
||||
let TSFlags{6-0} = FormBits;
|
||||
let TSFlags{8-7} = OpSizeBits;
|
||||
|
|
|
@ -7166,7 +7166,8 @@ defm VMASKMOVPD : avx_movmask_rm<0x2D, 0x2F, "vmaskmovpd",
|
|||
//===----------------------------------------------------------------------===//
|
||||
// AVX_VNNI
|
||||
//===----------------------------------------------------------------------===//
|
||||
let Predicates = [HasAVXVNNI, NoVLX_Or_NoVNNI], Constraints = "$src1 = $dst" in
|
||||
let Predicates = [HasAVXVNNI, NoVLX_Or_NoVNNI], Constraints = "$src1 = $dst",
|
||||
ExplicitVEXPrefix = 1, checkVEXPredicate = 1 in
|
||||
multiclass avx_vnni_rm<bits<8> opc, string OpcodeStr, SDNode OpNode,
|
||||
bit IsCommutable> {
|
||||
let isCommutable = IsCommutable in
|
||||
|
@ -7200,10 +7201,10 @@ multiclass avx_vnni_rm<bits<8> opc, string OpcodeStr, SDNode OpNode,
|
|||
VEX_4V, VEX_L, Sched<[SchedWriteVecIMul.XMM]>;
|
||||
}
|
||||
|
||||
defm VPDPBUSD : avx_vnni_rm<0x50, "vpdpbusd", X86Vpdpbusd, 0>, ExplicitVEXPrefix;
|
||||
defm VPDPBUSDS : avx_vnni_rm<0x51, "vpdpbusds", X86Vpdpbusds, 0>, ExplicitVEXPrefix;
|
||||
defm VPDPWSSD : avx_vnni_rm<0x52, "vpdpwssd", X86Vpdpwssd, 1>, ExplicitVEXPrefix;
|
||||
defm VPDPWSSDS : avx_vnni_rm<0x53, "vpdpwssds", X86Vpdpwssds, 1>, ExplicitVEXPrefix;
|
||||
defm VPDPBUSD : avx_vnni_rm<0x50, "vpdpbusd", X86Vpdpbusd, 0>;
|
||||
defm VPDPBUSDS : avx_vnni_rm<0x51, "vpdpbusds", X86Vpdpbusds, 0>;
|
||||
defm VPDPWSSD : avx_vnni_rm<0x52, "vpdpwssd", X86Vpdpwssd, 1>;
|
||||
defm VPDPWSSDS : avx_vnni_rm<0x53, "vpdpwssds", X86Vpdpwssds, 1>;
|
||||
|
||||
def X86vpmaddwd_su : PatFrag<(ops node:$lhs, node:$rhs),
|
||||
(X86vpmaddwd node:$lhs, node:$rhs), [{
|
||||
|
|
|
@ -30,10 +30,13 @@ class X86EVEX2VEXTablesEmitter {
|
|||
std::map<uint64_t, std::vector<const CodeGenInstruction *>> VEXInsts;
|
||||
|
||||
typedef std::pair<const CodeGenInstruction *, const CodeGenInstruction *> Entry;
|
||||
typedef std::pair<StringRef, StringRef> Predicate;
|
||||
|
||||
// Represent both compress tables
|
||||
std::vector<Entry> EVEX2VEX128;
|
||||
std::vector<Entry> EVEX2VEX256;
|
||||
// Represent predicates of VEX instructions.
|
||||
std::vector<Predicate> EVEX2VEXPredicates;
|
||||
|
||||
public:
|
||||
X86EVEX2VEXTablesEmitter(RecordKeeper &R) : Records(R), Target(R) {}
|
||||
|
@ -45,6 +48,9 @@ private:
|
|||
// Prints the given table as a C++ array of type
|
||||
// X86EvexToVexCompressTableEntry
|
||||
void printTable(const std::vector<Entry> &Table, raw_ostream &OS);
|
||||
// Prints function which checks target feature specific predicate.
|
||||
void printCheckPredicate(const std::vector<Predicate> &Predicates,
|
||||
raw_ostream &OS);
|
||||
};
|
||||
|
||||
void X86EVEX2VEXTablesEmitter::printTable(const std::vector<Entry> &Table,
|
||||
|
@ -67,6 +73,19 @@ void X86EVEX2VEXTablesEmitter::printTable(const std::vector<Entry> &Table,
|
|||
OS << "};\n\n";
|
||||
}
|
||||
|
||||
void X86EVEX2VEXTablesEmitter::printCheckPredicate(
|
||||
const std::vector<Predicate> &Predicates, raw_ostream &OS) {
|
||||
OS << "static bool CheckVEXInstPredicate"
|
||||
<< "(MachineInstr &MI, const X86Subtarget *Subtarget) {\n"
|
||||
<< " unsigned Opc = MI.getOpcode();\n"
|
||||
<< " switch (Opc) {\n"
|
||||
<< " default: return true;\n";
|
||||
for (auto Pair : Predicates)
|
||||
OS << " case X86::" << Pair.first << ": return " << Pair.second << ";\n";
|
||||
OS << " }\n"
|
||||
<< "}\n\n";
|
||||
}
|
||||
|
||||
// Return true if the 2 BitsInits are equal
|
||||
// Calculates the integer value residing BitsInit object
|
||||
static inline uint64_t getValueFromBitsInit(const BitsInit *B) {
|
||||
|
@ -169,6 +188,18 @@ private:
|
|||
};
|
||||
|
||||
void X86EVEX2VEXTablesEmitter::run(raw_ostream &OS) {
|
||||
auto getPredicates = [&](const CodeGenInstruction *Inst) {
|
||||
std::vector<Record *> PredicatesRecords =
|
||||
Inst->TheDef->getValueAsListOfDefs("Predicates");
|
||||
// Currently we only do AVX related checks and assume each instruction
|
||||
// has one and only one AVX related predicates.
|
||||
for (unsigned i = 0, e = PredicatesRecords.size(); i != e; ++i)
|
||||
if (PredicatesRecords[i]->getName().startswith("HasAVX"))
|
||||
return PredicatesRecords[i]->getValueAsString("CondString");
|
||||
llvm_unreachable(
|
||||
"Instruction with checkPredicate set must have one predicate!");
|
||||
};
|
||||
|
||||
emitSourceFileHeader("X86 EVEX2VEX tables", OS);
|
||||
|
||||
ArrayRef<const CodeGenInstruction *> NumberedInstructions =
|
||||
|
@ -222,11 +253,18 @@ void X86EVEX2VEXTablesEmitter::run(raw_ostream &OS) {
|
|||
EVEX2VEX256.push_back(std::make_pair(EVEXInst, VEXInst)); // {0,1}
|
||||
else
|
||||
EVEX2VEX128.push_back(std::make_pair(EVEXInst, VEXInst)); // {0,0}
|
||||
|
||||
// Adding predicate check to EVEX2VEXPredicates table when needed.
|
||||
if (VEXInst->TheDef->getValueAsBit("checkVEXPredicate"))
|
||||
EVEX2VEXPredicates.push_back(
|
||||
std::make_pair(EVEXInst->TheDef->getName(), getPredicates(VEXInst)));
|
||||
}
|
||||
|
||||
// Print both tables
|
||||
printTable(EVEX2VEX128, OS);
|
||||
printTable(EVEX2VEX256, OS);
|
||||
// Print CheckVEXInstPredicate function.
|
||||
printCheckPredicate(EVEX2VEXPredicates, OS);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue