Filter out repeated sections from the X86 disassembler modRMTable. Saves about ~43K from a released build. Unfortunately the disassembler tables are still upwards of 800K.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191652 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Craig Topper 2013-09-30 06:23:19 +00:00
parent 6b85c4e561
commit 39004b537b
2 changed files with 67 additions and 87 deletions

View File

@ -265,35 +265,6 @@ static inline const char* stringForOperandEncoding(OperandEncoding encoding) {
}
}
void DisassemblerTables::emitOneID(raw_ostream &o, unsigned &i, InstrUID id,
bool addComma) const {
if (id)
o.indent(i * 2) << format("0x%hx", id);
else
o.indent(i * 2) << 0;
if (addComma)
o << ", ";
else
o << " ";
o << "/* ";
o << InstructionSpecifiers[id].name;
o << "*/";
o << "\n";
}
/// emitEmptyTable - Emits the modRMEmptyTable, which is used as a ID table by
/// all ModR/M decisions for instructions that are invalid for all possible
/// ModR/M byte values.
///
/// @param o - The output stream on which to emit the table.
/// @param i - The indentation level for that output stream.
static void emitEmptyTable(raw_ostream &o, unsigned &i) {
o.indent(i * 2) << "0x0, /* EmptyTable */\n";
}
/// getDecisionType - Determines whether a ModRM decision with 255 entries can
/// be compacted by eliminating redundant information.
///
@ -393,6 +364,7 @@ DisassemblerTables::~DisassemblerTables() {
void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2,
unsigned &i1, unsigned &i2,
unsigned &ModRMTableNum,
ModRMDecision &decision) const {
static uint32_t sTableNumber = 0;
static uint32_t sEntryNumber = 1;
@ -411,44 +383,56 @@ void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2,
return;
}
o1 << "/* Table" << sTableNumber << " */\n";
i1++;
std::vector<unsigned> ModRMDecision;
switch (dt) {
default:
llvm_unreachable("Unknown decision type");
case MODRM_ONEENTRY:
emitOneID(o1, i1, decision.instructionIDs[0], true);
ModRMDecision.push_back(decision.instructionIDs[0]);
break;
case MODRM_SPLITRM:
emitOneID(o1, i1, decision.instructionIDs[0x00], true); // mod = 0b00
emitOneID(o1, i1, decision.instructionIDs[0xc0], true); // mod = 0b11
ModRMDecision.push_back(decision.instructionIDs[0x00]);
ModRMDecision.push_back(decision.instructionIDs[0xc0]);
break;
case MODRM_SPLITREG:
for (unsigned index = 0; index < 64; index += 8)
emitOneID(o1, i1, decision.instructionIDs[index], true);
ModRMDecision.push_back(decision.instructionIDs[index]);
for (unsigned index = 0xc0; index < 256; index += 8)
emitOneID(o1, i1, decision.instructionIDs[index], true);
ModRMDecision.push_back(decision.instructionIDs[index]);
break;
case MODRM_SPLITMISC:
for (unsigned index = 0; index < 64; index += 8)
emitOneID(o1, i1, decision.instructionIDs[index], true);
ModRMDecision.push_back(decision.instructionIDs[index]);
for (unsigned index = 0xc0; index < 256; ++index)
emitOneID(o1, i1, decision.instructionIDs[index], true);
ModRMDecision.push_back(decision.instructionIDs[index]);
break;
case MODRM_FULL:
for (unsigned index = 0; index < 256; ++index)
emitOneID(o1, i1, decision.instructionIDs[index], true);
ModRMDecision.push_back(decision.instructionIDs[index]);
break;
}
i1--;
unsigned &EntryNumber = ModRMTable[ModRMDecision];
if (EntryNumber == 0) {
EntryNumber = ModRMTableNum;
ModRMTableNum += ModRMDecision.size();
o1 << "/* Table" << EntryNumber << " */\n";
i1++;
for (std::vector<unsigned>::const_iterator I = ModRMDecision.begin(),
E = ModRMDecision.end(); I != E; ++I) {
o1.indent(i1 * 2) << format("0x%hx", *I) << ", /* "
<< InstructionSpecifiers[*I].name << " */\n";
}
i1--;
}
o2.indent(i2) << "{ /* struct ModRMDecision */" << "\n";
i2++;
o2.indent(i2) << stringForDecisionType(dt) << "," << "\n";
o2.indent(i2) << sEntryNumber << " /* Table" << sTableNumber << " */\n";
o2.indent(i2) << EntryNumber << " /* Table" << EntryNumber << " */\n";
i2--;
o2.indent(i2) << "}";
@ -482,6 +466,7 @@ void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2,
void DisassemblerTables::emitOpcodeDecision(raw_ostream &o1, raw_ostream &o2,
unsigned &i1, unsigned &i2,
unsigned &ModRMTableNum,
OpcodeDecision &decision) const {
o2.indent(i2) << "{ /* struct OpcodeDecision */" << "\n";
i2++;
@ -493,7 +478,8 @@ void DisassemblerTables::emitOpcodeDecision(raw_ostream &o1, raw_ostream &o2,
o2 << "/* 0x" << format("%02hhx", index) << " */" << "\n";
emitModRMDecision(o1, o2, i1, i2, decision.modRMDecisions[index]);
emitModRMDecision(o1, o2, i1, i2, ModRMTableNum,
decision.modRMDecisions[index]);
if (index < 255)
o2 << ",";
@ -509,6 +495,7 @@ void DisassemblerTables::emitOpcodeDecision(raw_ostream &o1, raw_ostream &o2,
void DisassemblerTables::emitContextDecision(raw_ostream &o1, raw_ostream &o2,
unsigned &i1, unsigned &i2,
unsigned &ModRMTableNum,
ContextDecision &decision,
const char* name) const {
o2.indent(i2) << "static const struct ContextDecision " << name << " = {\n";
@ -522,7 +509,8 @@ void DisassemblerTables::emitContextDecision(raw_ostream &o1, raw_ostream &o2,
o2 << " */";
o2 << "\n";
emitOpcodeDecision(o1, o2, i1, i2, decision.opcodeDecisions[index]);
emitOpcodeDecision(o1, o2, i1, i2, ModRMTableNum,
decision.opcodeDecisions[index]);
if (index + 1 < IC_max)
o2 << ", ";
@ -711,13 +699,14 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
}
void DisassemblerTables::emitContextDecisions(raw_ostream &o1, raw_ostream &o2,
unsigned &i1, unsigned &i2) const {
emitContextDecision(o1, o2, i1, i2, *Tables[0], ONEBYTE_STR);
emitContextDecision(o1, o2, i1, i2, *Tables[1], TWOBYTE_STR);
emitContextDecision(o1, o2, i1, i2, *Tables[2], THREEBYTE38_STR);
emitContextDecision(o1, o2, i1, i2, *Tables[3], THREEBYTE3A_STR);
emitContextDecision(o1, o2, i1, i2, *Tables[4], THREEBYTEA6_STR);
emitContextDecision(o1, o2, i1, i2, *Tables[5], THREEBYTEA7_STR);
unsigned &i1, unsigned &i2,
unsigned &ModRMTableNum) const {
emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[0], ONEBYTE_STR);
emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[1], TWOBYTE_STR);
emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[2], THREEBYTE38_STR);
emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[3], THREEBYTE3A_STR);
emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[4], THREEBYTEA6_STR);
emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[5], THREEBYTEA7_STR);
}
void DisassemblerTables::emit(raw_ostream &o) const {
@ -736,11 +725,17 @@ void DisassemblerTables::emit(raw_ostream &o) const {
emitContextTable(o, i2);
o << "\n";
unsigned ModRMTableNum = 0;
o << "static const InstrUID modRMTable[] = {\n";
i1++;
emitEmptyTable(o1, i1);
std::vector<unsigned> EmptyTable(1, 0);
ModRMTable[EmptyTable] = ModRMTableNum;
ModRMTableNum += EmptyTable.size();
o1 << "/* EmptyTable */\n";
o1.indent(i1 * 2) << "0x0,\n";
i1--;
emitContextDecisions(o1, o2, i1, i2);
emitContextDecisions(o1, o2, i1, i2, ModRMTableNum);
o << o1.str();
o << " 0x0\n";

View File

@ -20,6 +20,7 @@
#include "X86DisassemblerShared.h"
#include "X86ModRMFilters.h"
#include "llvm/Support/raw_ostream.h"
#include <map>
#include <vector>
namespace llvm {
@ -41,28 +42,16 @@ private:
/// [5] three-byte opcodes of the form 0f a7 __
ContextDecision* Tables[6];
// Table of ModRM encodings.
typedef std::map<std::vector<unsigned>, unsigned> ModRMMapTy;
mutable ModRMMapTy ModRMTable;
/// The instruction information table
std::vector<InstructionSpecifier> InstructionSpecifiers;
/// True if there are primary decode conflicts in the instruction set
bool HasConflicts;
/// emitOneID - Emits a table entry for a single instruction entry, at the
/// innermost level of the structure hierarchy. The entry is printed out
/// in the format "nnnn, /* MNEMONIC */" where nnnn is the ID in decimal,
/// the comma is printed if addComma is true, and the menonic is the name
/// of the instruction as listed in the LLVM tables.
///
/// @param o - The output stream to print the entry on.
/// @param i - The indentation level for o.
/// @param id - The unique ID of the instruction to print.
/// @param addComma - Whether or not to print a comma after the ID. True if
/// additional items will follow.
void emitOneID(raw_ostream &o,
uint32_t &i,
InstrUID id,
bool addComma) const;
/// emitModRMDecision - Emits a table of entries corresponding to a single
/// ModR/M decision. Compacts the ModR/M decision if possible. ModR/M
/// decisions are printed as:
@ -91,12 +80,11 @@ private:
/// @param o2 - The output stream to print the decision structure to.
/// @param i1 - The indentation level to use with stream o1.
/// @param i2 - The indentation level to use with stream o2.
/// @param ModRMTableNum - next table number for adding to ModRMTable.
/// @param decision - The ModR/M decision to emit. This decision has 256
/// entries - emitModRMDecision decides how to compact it.
void emitModRMDecision(raw_ostream &o1,
raw_ostream &o2,
uint32_t &i1,
uint32_t &i2,
void emitModRMDecision(raw_ostream &o1, raw_ostream &o2,
unsigned &i1, unsigned &i2, unsigned &ModRMTableNum,
ModRMDecision &decision) const;
/// emitOpcodeDecision - Emits an OpcodeDecision and all its subsidiary ModR/M
@ -120,12 +108,11 @@ private:
/// @param o2 - The output stream for the decision structure itself.
/// @param i1 - The indent level to use with stream o1.
/// @param i2 - The indent level to use with stream o2.
/// @param ModRMTableNum - next table number for adding to ModRMTable.
/// @param decision - The OpcodeDecision to emit along with its subsidiary
/// structures.
void emitOpcodeDecision(raw_ostream &o1,
raw_ostream &o2,
uint32_t &i1,
uint32_t &i2,
void emitOpcodeDecision(raw_ostream &o1, raw_ostream &o2,
unsigned &i1, unsigned &i2, unsigned &ModRMTableNum,
OpcodeDecision &decision) const;
/// emitContextDecision - Emits a ContextDecision and all its subsidiary
@ -155,15 +142,13 @@ private:
/// @param o2 - The output stream to print the decision structure to.
/// @param i1 - The indent level to use with stream o1.
/// @param i2 - The indent level to use with stream o2.
/// @param ModRMTableNum - next table number for adding to ModRMTable.
/// @param decision - The ContextDecision to emit along with its subsidiary
/// structures.
/// @param name - The name for the ContextDecision.
void emitContextDecision(raw_ostream &o1,
raw_ostream &o2,
uint32_t &i1,
uint32_t &i2,
ContextDecision &decision,
const char* name) const;
void emitContextDecision(raw_ostream &o1, raw_ostream &o2,
unsigned &i1, unsigned &i2, unsigned &ModRMTableNum,
ContextDecision &decision, const char* name) const;
/// emitInstructionInfo - Prints the instruction specifier table, which has
/// one entry for each instruction, and contains name and operand
@ -194,7 +179,7 @@ private:
/// @param o - The output stream to which the instruction table should be
/// written.
/// @param i - The indent level for use with the stream.
void emitInstructionInfo(raw_ostream &o, uint32_t &i) const;
void emitInstructionInfo(raw_ostream &o, unsigned &i) const;
/// emitContextTable - Prints the table that is used to translate from an
/// instruction attribute mask to an instruction context. This table is
@ -220,10 +205,10 @@ private:
/// @param o2 - The output stream to print the decision structures to.
/// @param i1 - The indent level to use with stream o1.
/// @param i2 - The indent level to use with stream o2.
void emitContextDecisions(raw_ostream &o1,
raw_ostream &o2,
uint32_t &i1,
uint32_t &i2) const;
/// @param ModRMTableNum - next table number for adding to ModRMTable.
void emitContextDecisions(raw_ostream &o1, raw_ostream &o2,
unsigned &i1, unsigned &i2,
unsigned &ModRMTableNum) const;
/// setTableFields - Uses a ModRMFilter to set the appropriate entries in a
/// ModRMDecision to refer to a particular instruction ID.