aboutsummaryrefslogtreecommitdiff
path: root/utils/TableGen
diff options
context:
space:
mode:
authorManman Ren <mren@apple.com>2012-09-13 17:43:46 +0000
committerManman Ren <mren@apple.com>2012-09-13 17:43:46 +0000
commit6579cf8df6cfcfe81519df7389f33832d9b4a59f (patch)
treec7a62ec6cac998c365be716ac0bc2beced13e31e /utils/TableGen
parente6ac7d69d3308d580a87ff3e3645f98e2bc565a5 (diff)
AsmWriterEmitter: increase the number of bits for OpcodeInfo from 32-bit to
48-bit if necessary, in order to reduce the generated code size. We have 900 cases not covered by OpcodeInfo in ATT AsmWriter and more in Intel AsmWriter and ARM AsmWriter. This patch reduced the clang Release build size by 50k, running on a Mac Pro. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163814 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils/TableGen')
-rw-r--r--utils/TableGen/AsmWriterEmitter.cpp57
1 files changed, 46 insertions, 11 deletions
diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp
index 57979b3e6d..56b2ef82b6 100644
--- a/utils/TableGen/AsmWriterEmitter.cpp
+++ b/utils/TableGen/AsmWriterEmitter.cpp
@@ -313,7 +313,9 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
/// OpcodeInfo - This encodes the index of the string to use for the first
/// chunk of the output as well as indices used for operand printing.
- std::vector<unsigned> OpcodeInfo;
+ /// To reduce the number of unhandled cases, we expand the size from 32-bit
+ /// to 32+16 = 48-bit.
+ std::vector<std::pair<unsigned, uint16_t> > OpcodeInfo;
// Add all strings to the string table upfront so it can generate an optimized
// representation.
@@ -354,7 +356,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
}
// Bias offset by one since we want 0 as a sentinel.
- OpcodeInfo.push_back(Idx+1);
+ OpcodeInfo.push_back(std::make_pair(Idx+1, 0));
}
// Figure out how many bits we used for the string index.
@@ -362,7 +364,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
// To reduce code size, we compactify common instructions into a few bits
// in the opcode-indexed table.
- unsigned BitsLeft = 32-AsmStrBits;
+ unsigned BitsLeft = 32+16-AsmStrBits;
std::vector<std::vector<std::string> > TableDrivenOperandPrinters;
@@ -380,6 +382,13 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
// ceil(log2(numentries)).
unsigned NumBits = Log2_32_Ceil(UniqueOperandCommands.size());
+ // Check whether these Bits will fit in the first 32 bits.
+ if (BitsLeft > 16 && NumBits > BitsLeft - 16)
+ // We don't have enough bits in the first 32 bits, and we skip the
+ // left-over bits.
+ BitsLeft = 16;
+ bool UseSecond = (BitsLeft <= 16);
+
// If we don't have enough bits for this operand, don't include it.
if (NumBits > BitsLeft) {
DEBUG(errs() << "Not enough bits to densely encode " << NumBits
@@ -390,8 +399,13 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
// Otherwise, we can include this in the initial lookup table. Add it in.
BitsLeft -= NumBits;
for (unsigned i = 0, e = InstIdxs.size(); i != e; ++i)
- if (InstIdxs[i] != ~0U)
- OpcodeInfo[i] |= InstIdxs[i] << (BitsLeft+AsmStrBits);
+ // Update the first 32 bits or the second 16 bits.
+ if (InstIdxs[i] != ~0U) {
+ if (UseSecond)
+ OpcodeInfo[i].second |= InstIdxs[i] << BitsLeft;
+ else
+ OpcodeInfo[i].first |= InstIdxs[i] << (BitsLeft-16+AsmStrBits);
+ }
// Remove the info about this operand.
for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
@@ -413,13 +427,25 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
O<<" static const unsigned OpInfo[] = {\n";
for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
- O << " " << OpcodeInfo[i] << "U,\t// "
+ O << " " << OpcodeInfo[i].first << "U,\t// "
<< NumberedInstructions[i]->TheDef->getName() << "\n";
}
// Add a dummy entry so the array init doesn't end with a comma.
O << " 0U\n";
O << " };\n\n";
+ if (BitsLeft < 16) {
+ // Add a second OpInfo table only when it is necessary.
+ O<<" static const short OpInfo2[] = {\n";
+ for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
+ O << " " << OpcodeInfo[i].second << "U,\t// "
+ << NumberedInstructions[i]->TheDef->getName() << "\n";
+ }
+ // Add a dummy entry so the array init doesn't end with a comma.
+ O << " 0U\n";
+ O << " };\n\n";
+ }
+
// Emit the string itself.
O << " const char AsmStrs[] = {\n";
StringTable.emit(O, printChar);
@@ -428,12 +454,14 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
O << " O << \"\\t\";\n\n";
O << " // Emit the opcode for the instruction.\n"
- << " unsigned Bits = OpInfo[MI->getOpcode()];\n"
- << " assert(Bits != 0 && \"Cannot print this instruction.\");\n"
+ << " unsigned Bits = OpInfo[MI->getOpcode()];\n";
+ if (BitsLeft < 16)
+ O << " unsigned short Bits2 = OpInfo2[MI->getOpcode()];\n";
+ O << " assert(Bits != 0 && \"Cannot print this instruction.\");\n"
<< " O << AsmStrs+(Bits & " << (1 << AsmStrBits)-1 << ")-1;\n\n";
// Output the table driven operand information.
- BitsLeft = 32-AsmStrBits;
+ BitsLeft = 32+16-AsmStrBits;
for (unsigned i = 0, e = TableDrivenOperandPrinters.size(); i != e; ++i) {
std::vector<std::string> &Commands = TableDrivenOperandPrinters[i];
@@ -442,6 +470,11 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
unsigned NumBits = Log2_32_Ceil(Commands.size());
assert(NumBits <= BitsLeft && "consistency error");
+ // Check whether these Bits will fit in the first 32 bits.
+ if (BitsLeft > 16 && NumBits > BitsLeft - 16)
+ BitsLeft = 16;
+ bool UseSecond = (BitsLeft <= 16);
+
// Emit code to extract this field from Bits.
BitsLeft -= NumBits;
@@ -450,7 +483,8 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
if (Commands.size() == 2) {
// Emit two possibilitys with if/else.
- O << " if ((Bits >> " << (BitsLeft+AsmStrBits) << ") & "
+ O << (UseSecond ? " if ((Bits2 >> " : " if ((Bits >> ")
+ << (UseSecond ? BitsLeft : (BitsLeft-16+AsmStrBits)) << ") & "
<< ((1 << NumBits)-1) << ") {\n"
<< Commands[1]
<< " } else {\n"
@@ -460,7 +494,8 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
// Emit a single possibility.
O << Commands[0] << "\n\n";
} else {
- O << " switch ((Bits >> " << (BitsLeft+AsmStrBits) << ") & "
+ O << (UseSecond ? " switch ((Bits2 >> " : " switch ((Bits >> ")
+ << (UseSecond ? BitsLeft : (BitsLeft-16+AsmStrBits)) << ") & "
<< ((1 << NumBits)-1) << ") {\n"
<< " default: // unreachable.\n";