[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:
Liu, Chen3 2021-03-05 15:11:20 +08:00
parent 0875c2f7f6
commit 3618b21298
4 changed files with 49 additions and 24 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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), [{

View File

@ -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);
}
}