From 6579cf8df6cfcfe81519df7389f33832d9b4a59f Mon Sep 17 00:00:00 2001 From: Manman Ren Date: Thu, 13 Sep 2012 17:43:46 +0000 Subject: 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 --- utils/TableGen/AsmWriterEmitter.cpp | 57 ++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 11 deletions(-) (limited to 'utils/TableGen/AsmWriterEmitter.cpp') diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index 57979b3e6db..56b2ef82b66 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 OpcodeInfo; + /// To reduce the number of unhandled cases, we expand the size from 32-bit + /// to 32+16 = 48-bit. + std::vector > 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 > 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 &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"; -- cgit v1.2.3