Skip to content

Commit 17ecd23

Browse files
committed
[X86][tablgen] Extend X86CompressEVEXTablesEmitter for NF transform
The generated table will be used in #93508
1 parent 98f9bb3 commit 17ecd23

File tree

4 files changed

+109
-61
lines changed

4 files changed

+109
-61
lines changed

llvm/lib/Target/X86/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ tablegen(LLVM X86GenAsmWriter1.inc -gen-asm-writer -asmwriternum=1)
88
tablegen(LLVM X86GenCallingConv.inc -gen-callingconv)
99
tablegen(LLVM X86GenDAGISel.inc -gen-dag-isel)
1010
tablegen(LLVM X86GenDisassemblerTables.inc -gen-disassembler)
11-
tablegen(LLVM X86GenCompressEVEXTables.inc -gen-x86-compress-evex-tables)
11+
tablegen(LLVM X86GenInstrMapping.inc -gen-x86-instr-mapping)
1212
tablegen(LLVM X86GenExegesis.inc -gen-exegesis)
1313
tablegen(LLVM X86GenFastISel.inc -gen-fast-isel)
1414
tablegen(LLVM X86GenGlobalISel.inc -gen-global-isel)

llvm/lib/Target/X86/X86CompressEVEX.cpp

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -50,27 +50,15 @@
5050

5151
using namespace llvm;
5252

53-
// Including the generated EVEX compression tables.
54-
struct X86CompressEVEXTableEntry {
55-
uint16_t OldOpc;
56-
uint16_t NewOpc;
57-
58-
bool operator<(const X86CompressEVEXTableEntry &RHS) const {
59-
return OldOpc < RHS.OldOpc;
60-
}
61-
62-
friend bool operator<(const X86CompressEVEXTableEntry &TE, unsigned Opc) {
63-
return TE.OldOpc < Opc;
64-
}
65-
};
66-
#include "X86GenCompressEVEXTables.inc"
67-
6853
#define COMP_EVEX_DESC "Compressing EVEX instrs when possible"
6954
#define COMP_EVEX_NAME "x86-compress-evex"
7055

7156
#define DEBUG_TYPE COMP_EVEX_NAME
7257

7358
namespace {
59+
// Including the generated EVEX compression tables.
60+
#define GET_X86_COMPRESS_EVEX_TABLE
61+
#include "X86GenInstrMapping.inc"
7462

7563
class CompressEVEXPass : public MachineFunctionPass {
7664
public:
@@ -234,7 +222,7 @@ static bool CompressEVEXImpl(MachineInstr &MI, const X86Subtarget &ST) {
234222
if (IsNDLike && !isRedundantNewDataDest(MI, ST))
235223
return false;
236224

237-
ArrayRef<X86CompressEVEXTableEntry> Table = ArrayRef(X86CompressEVEXTable);
225+
ArrayRef<X86TableEntry> Table = ArrayRef(X86CompressEVEXTable);
238226

239227
Opc = MI.getOpcode();
240228
const auto *I = llvm::lower_bound(Table, Opc);

llvm/utils/TableGen/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ add_tablegen(llvm-tblgen LLVM
7070
TableGen.cpp
7171
VTEmitter.cpp
7272
WebAssemblyDisassemblerEmitter.cpp
73-
X86CompressEVEXTablesEmitter.cpp
73+
X86InstrMappingEmitter.cpp
7474
X86DisassemblerTables.cpp
7575
X86FoldTablesEmitter.cpp
7676
X86MnemonicTables.cpp

llvm/utils/TableGen/X86CompressEVEXTablesEmitter.cpp renamed to llvm/utils/TableGen/X86InstrMappingEmitter.cpp

Lines changed: 103 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
//==- utils/TableGen/X86CompressEVEXTablesEmitter.cpp - X86 backend-*- C++ -*-//
1+
//========- utils/TableGen/X86InstrMappingEmitter.cpp - X86 backend-*- C++ -*-//
22
//
33
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44
// See https://llvm.org/LICENSE.txt for license information.
55
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66
//
77
//===----------------------------------------------------------------------===//
88
///
9-
/// This tablegen backend is responsible for emitting the X86 backend EVEX
10-
/// compression tables.
9+
/// This tablegen backend is responsible for emitting the X86 backend
10+
/// instruction mapping.
1111
///
1212
//===----------------------------------------------------------------------===//
1313

@@ -34,7 +34,7 @@ const std::set<StringRef> NoCompressSet = {
3434
#include "X86ManualCompressEVEXTables.def"
3535
};
3636

37-
class X86CompressEVEXTablesEmitter {
37+
class X86InstrMappingEmitter {
3838
RecordKeeper &Records;
3939
CodeGenTarget Target;
4040

@@ -49,52 +49,67 @@ class X86CompressEVEXTablesEmitter {
4949
typedef std::map<StringRef, std::vector<const CodeGenInstruction *>>
5050
PredicateInstMap;
5151

52-
std::vector<Entry> Table;
5352
// Hold all compressed instructions that need to check predicate
5453
PredicateInstMap PredicateInsts;
5554

5655
public:
57-
X86CompressEVEXTablesEmitter(RecordKeeper &R) : Records(R), Target(R) {}
56+
X86InstrMappingEmitter(RecordKeeper &R) : Records(R), Target(R) {}
5857

5958
// run - Output X86 EVEX compression tables.
6059
void run(raw_ostream &OS);
6160

6261
private:
63-
// Prints the given table as a C++ array of type X86CompressEVEXTableEntry
64-
void printTable(const std::vector<Entry> &Table, raw_ostream &OS);
65-
// Prints function which checks target feature for compressed instructions.
66-
void printCheckPredicate(const PredicateInstMap &PredicateInsts,
67-
raw_ostream &OS);
62+
void emitCompressEVEXTable(ArrayRef<const CodeGenInstruction *> Insts,
63+
raw_ostream &OS);
64+
void emitNFTransformTable(ArrayRef<const CodeGenInstruction *> Insts,
65+
raw_ostream &OS);
66+
67+
// Prints the definition of class X86TableEntry.
68+
void printClassDef(raw_ostream &OS);
69+
// Prints the given table as a C++ array of type X86TableEntry under the guard
70+
// \p Macro.
71+
void printTable(const std::vector<Entry> &Table, StringRef Name,
72+
StringRef Macro, raw_ostream &OS);
6873
};
6974

70-
void X86CompressEVEXTablesEmitter::printTable(const std::vector<Entry> &Table,
71-
raw_ostream &OS) {
75+
void X86InstrMappingEmitter::printClassDef(raw_ostream &OS) {
76+
OS << "struct X86TableEntry {\n"
77+
" uint16_t OldOpc;\n"
78+
" uint16_t NewOpc;\n"
79+
" bool operator<(const X86TableEntry &RHS) const {\n"
80+
" return OldOpc < RHS.OldOpc;\n"
81+
" }"
82+
" friend bool operator<(const X86TableEntry &TE, unsigned Opc) {\n"
83+
" return TE.OldOpc < Opc;\n"
84+
" }\n"
85+
"};";
86+
87+
OS << "\n\n";
88+
}
89+
90+
static void printMacroBegin(StringRef Macro, raw_ostream &OS) {
91+
OS << "\n#ifdef " << Macro << "\n";
92+
}
93+
94+
static void printMacroEnd(StringRef Macro, raw_ostream &OS) {
95+
OS << "#endif // " << Macro << "\n\n";
96+
}
7297

73-
OS << "static const X86CompressEVEXTableEntry X86CompressEVEXTable[] = {\n";
98+
void X86InstrMappingEmitter::printTable(const std::vector<Entry> &Table,
99+
StringRef Name, StringRef Macro,
100+
raw_ostream &OS) {
101+
printMacroBegin(Macro, OS);
102+
103+
OS << "static const X86TableEntry " << Name << "[] = {\n";
74104

75105
// Print all entries added to the table
76106
for (const auto &Pair : Table)
77107
OS << " { X86::" << Pair.first->TheDef->getName()
78108
<< ", X86::" << Pair.second->TheDef->getName() << " },\n";
79109

80110
OS << "};\n\n";
81-
}
82-
83-
void X86CompressEVEXTablesEmitter::printCheckPredicate(
84-
const PredicateInstMap &PredicateInsts, raw_ostream &OS) {
85-
86-
OS << "static bool checkPredicate(unsigned Opc, const X86Subtarget "
87-
"*Subtarget) {\n"
88-
<< " switch (Opc) {\n"
89-
<< " default: return true;\n";
90-
for (const auto &[Key, Val] : PredicateInsts) {
91-
for (const auto &Inst : Val)
92-
OS << " case X86::" << Inst->TheDef->getName() << ":\n";
93-
OS << " return " << Key << ";\n";
94-
}
95111

96-
OS << " }\n";
97-
OS << "}\n\n";
112+
printMacroEnd(Macro, OS);
98113
}
99114

100115
static uint8_t byteFromBitsInit(const BitsInit *B) {
@@ -150,18 +165,19 @@ class IsMatch {
150165
}
151166
};
152167

153-
void X86CompressEVEXTablesEmitter::run(raw_ostream &OS) {
154-
emitSourceFileHeader("X86 EVEX compression tables", OS);
155-
156-
ArrayRef<const CodeGenInstruction *> NumberedInstructions =
157-
Target.getInstructionsByEnumValue();
168+
static bool isInteresting(const Record *Rec) {
169+
// _REV instruction should not appear before encoding optimization
170+
return Rec->isSubClassOf("X86Inst") &&
171+
!Rec->getValueAsBit("isAsmParserOnly") &&
172+
!Rec->getName().ends_with("_REV");
173+
}
158174

159-
for (const CodeGenInstruction *Inst : NumberedInstructions) {
175+
void X86InstrMappingEmitter::emitCompressEVEXTable(
176+
ArrayRef<const CodeGenInstruction *> Insts, raw_ostream &OS) {
177+
for (const CodeGenInstruction *Inst : Insts) {
160178
const Record *Rec = Inst->TheDef;
161179
StringRef Name = Rec->getName();
162-
// _REV instruction should not appear before encoding optimization
163-
if (!Rec->isSubClassOf("X86Inst") ||
164-
Rec->getValueAsBit("isAsmParserOnly") || Name.ends_with("_REV"))
180+
if (!isInteresting(Rec))
165181
continue;
166182

167183
// Promoted legacy instruction is in EVEX space, and has REX2-encoding
@@ -188,6 +204,7 @@ void X86CompressEVEXTablesEmitter::run(raw_ostream &OS) {
188204
PreCompressionInsts.push_back(Inst);
189205
}
190206

207+
std::vector<Entry> Table;
191208
for (const CodeGenInstruction *Inst : PreCompressionInsts) {
192209
const Record *Rec = Inst->TheDef;
193210
uint8_t Opcode = byteFromBitsInit(Rec->getValueAsBitsInit("Opcode"));
@@ -229,10 +246,53 @@ void X86CompressEVEXTablesEmitter::run(raw_ostream &OS) {
229246
PredicateInsts[(*It)->getValueAsString("CondString")].push_back(NewInst);
230247
}
231248

232-
printTable(Table, OS);
233-
printCheckPredicate(PredicateInsts, OS);
249+
StringRef Macro = "GET_X86_COMPRESS_EVEX_TABLE";
250+
printTable(Table, "X86CompressEVEXTable", Macro, OS);
251+
252+
// Prints function which checks target feature for compressed instructions.
253+
printMacroBegin(Macro, OS);
254+
OS << "static bool checkPredicate(unsigned Opc, const X86Subtarget "
255+
"*Subtarget) {\n"
256+
<< " switch (Opc) {\n"
257+
<< " default: return true;\n";
258+
for (const auto &[Key, Val] : PredicateInsts) {
259+
for (const auto &Inst : Val)
260+
OS << " case X86::" << Inst->TheDef->getName() << ":\n";
261+
OS << " return " << Key << ";\n";
262+
}
263+
OS << " }\n";
264+
OS << "}\n\n";
265+
printMacroEnd(Macro, OS);
266+
}
267+
268+
void X86InstrMappingEmitter::emitNFTransformTable(
269+
ArrayRef<const CodeGenInstruction *> Insts, raw_ostream &OS) {
270+
std::vector<Entry> Table;
271+
for (const CodeGenInstruction *Inst : Insts) {
272+
const Record *Rec = Inst->TheDef;
273+
if (!isInteresting(Rec))
274+
continue;
275+
std::string Name = Rec->getName().str();
276+
auto Pos = Name.find("_NF");
277+
if (Pos == std::string::npos)
278+
continue;
279+
280+
if (auto *NewRec = Records.getDef(Name.erase(Pos, 3)))
281+
Table.push_back(std::pair(&Target.getInstruction(NewRec), Inst));
282+
}
283+
printTable(Table, "X86NFTransformTable", "GET_X86_NF_TRANSFORM_TABLE", OS);
284+
}
285+
286+
void X86InstrMappingEmitter::run(raw_ostream &OS) {
287+
emitSourceFileHeader("X86 instruction mapping", OS);
288+
289+
ArrayRef<const CodeGenInstruction *> Insts =
290+
Target.getInstructionsByEnumValue();
291+
printClassDef(OS);
292+
emitCompressEVEXTable(Insts, OS);
293+
emitNFTransformTable(Insts, OS);
234294
}
235295
} // namespace
236296

237-
static TableGen::Emitter::OptClass<X86CompressEVEXTablesEmitter>
238-
X("gen-x86-compress-evex-tables", "Generate X86 EVEX compression tables");
297+
static TableGen::Emitter::OptClass<X86InstrMappingEmitter>
298+
X("gen-x86-instr-mapping", "Generate X86 instruction mapping");

0 commit comments

Comments
 (0)