forked from OSchip/llvm-project
Ok, I can't handle it. This is a temporary checkin of a ton of statistics that
i'm using in my work to reduce the bytecode file sizes. These will eventually be removed. llvm-svn: 10849
This commit is contained in:
parent
893b184db0
commit
9a38c78fe6
|
@ -16,15 +16,26 @@
|
|||
#include "llvm/Constants.h"
|
||||
#include "llvm/SymbolTable.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "Support/Statistic.h"
|
||||
using namespace llvm;
|
||||
|
||||
static Statistic<>
|
||||
TypeBytes("bytecodewriter", "Bytes of types");
|
||||
static Statistic<>
|
||||
ConstantBytes("bytecodewriter", "Bytes of constants");
|
||||
static Statistic<>
|
||||
NumConstants("bytecodewriter", "Number of constants");
|
||||
|
||||
void BytecodeWriter::outputType(const Type *T) {
|
||||
TypeBytes -= Out.size();
|
||||
output_vbr((unsigned)T->getPrimitiveID(), Out);
|
||||
|
||||
// That's all there is to handling primitive types...
|
||||
if (T->isPrimitiveType())
|
||||
if (T->isPrimitiveType()) {
|
||||
TypeBytes += Out.size();
|
||||
return; // We might do this if we alias a prim type: %x = type int
|
||||
|
||||
}
|
||||
|
||||
switch (T->getPrimitiveID()) { // Handle derived types now.
|
||||
case Type::FunctionTyID: {
|
||||
const FunctionType *MT = cast<FunctionType>(T);
|
||||
|
@ -95,12 +106,16 @@ void BytecodeWriter::outputType(const Type *T) {
|
|||
<< " Type '" << T->getDescription() << "'\n";
|
||||
break;
|
||||
}
|
||||
TypeBytes += Out.size();
|
||||
}
|
||||
|
||||
bool BytecodeWriter::outputConstant(const Constant *CPV) {
|
||||
ConstantBytes -= Out.size();
|
||||
assert((CPV->getType()->isPrimitiveType() || !CPV->isNullValue()) &&
|
||||
"Shouldn't output null constants!");
|
||||
|
||||
++NumConstants;
|
||||
|
||||
// We must check for a ConstantExpr before switching by type because
|
||||
// a ConstantExpr can be of any type, and has no explicit value.
|
||||
//
|
||||
|
@ -117,9 +132,10 @@ bool BytecodeWriter::outputConstant(const Constant *CPV) {
|
|||
Slot = Table.getSlot((*OI)->getType());
|
||||
output_vbr((unsigned)Slot, Out);
|
||||
}
|
||||
ConstantBytes += Out.size();
|
||||
return false;
|
||||
} else {
|
||||
output_vbr((unsigned)0, Out); // flag as not a ConstantExpr
|
||||
output_vbr(0U, Out); // flag as not a ConstantExpr
|
||||
}
|
||||
|
||||
switch (CPV->getType()->getPrimitiveID()) {
|
||||
|
@ -169,7 +185,7 @@ bool BytecodeWriter::outputConstant(const Constant *CPV) {
|
|||
int Slot = Table.getSlot(Vals[i]);
|
||||
assert(Slot != -1 && "Constant used but not available!!");
|
||||
output_vbr((unsigned)Slot, Out);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -199,5 +215,6 @@ bool BytecodeWriter::outputConstant(const Constant *CPV) {
|
|||
<< " type '" << CPV->getType()->getName() << "'\n";
|
||||
break;
|
||||
}
|
||||
ConstantBytes += Out.size();
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,23 @@ using namespace llvm;
|
|||
|
||||
static Statistic<>
|
||||
NumInstrs("bytecodewriter", "Number of instructions");
|
||||
static Statistic<>
|
||||
NumOversizedInstrs("bytecodewriter", "Number of oversized instructions");
|
||||
static Statistic<>
|
||||
BytesOversizedInstrs("bytecodewriter", "Bytes of oversized instructions");
|
||||
|
||||
static Statistic<>
|
||||
NumHugeOperandInstrs("bytecodewriter", "Number of instructions with > 3 operands");
|
||||
static Statistic<>
|
||||
NumOversized1OpInstrs("bytecodewriter", "Number of oversized 1 operand instrs");
|
||||
static Statistic<>
|
||||
NumOversized2OpInstrs("bytecodewriter", "Number of oversized 2 operand instrs");
|
||||
static Statistic<>
|
||||
NumOversized3OpInstrs("bytecodewriter", "Number of oversized 3 operand instrs");
|
||||
|
||||
static Statistic<>
|
||||
NumOversidedBecauseOfTypes("bytecodewriter", "Number of oversized instructions because of their type");
|
||||
|
||||
|
||||
typedef unsigned char uchar;
|
||||
|
||||
|
@ -33,6 +50,9 @@ typedef unsigned char uchar;
|
|||
static void outputInstructionFormat0(const Instruction *I, unsigned Opcode,
|
||||
const SlotCalculator &Table,
|
||||
unsigned Type, std::deque<uchar> &Out) {
|
||||
NumOversizedInstrs++;
|
||||
BytesOversizedInstrs -= Out.size();
|
||||
|
||||
// Opcode must have top two bits clear...
|
||||
output_vbr(Opcode << 2, Out); // Instruction Opcode ID
|
||||
output_vbr(Type, Out); // Result type
|
||||
|
@ -58,6 +78,7 @@ static void outputInstructionFormat0(const Instruction *I, unsigned Opcode,
|
|||
}
|
||||
|
||||
align32(Out); // We must maintain correct alignment!
|
||||
BytesOversizedInstrs += Out.size();
|
||||
}
|
||||
|
||||
|
||||
|
@ -275,6 +296,10 @@ void BytecodeWriter::processInstruction(const Instruction &I) {
|
|||
outputInstructionFormat1(&I, Opcode, Table, Slots, Type, Out);
|
||||
return;
|
||||
}
|
||||
if (Type >= (1 << 12)-1)
|
||||
NumOversidedBecauseOfTypes++;
|
||||
|
||||
NumOversized1OpInstrs++;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
@ -282,6 +307,9 @@ void BytecodeWriter::processInstruction(const Instruction &I) {
|
|||
outputInstructionFormat2(&I, Opcode, Table, Slots, Type, Out);
|
||||
return;
|
||||
}
|
||||
if (Type >= (1 << 8))
|
||||
NumOversidedBecauseOfTypes++;
|
||||
NumOversized2OpInstrs++;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
|
@ -289,6 +317,12 @@ void BytecodeWriter::processInstruction(const Instruction &I) {
|
|||
outputInstructionFormat3(&I, Opcode, Table, Slots, Type, Out);
|
||||
return;
|
||||
}
|
||||
if (Type >= (1 << 6))
|
||||
NumOversidedBecauseOfTypes++;
|
||||
NumOversized3OpInstrs++;
|
||||
break;
|
||||
default:
|
||||
++NumHugeOperandInstrs;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "llvm/DerivedTypes.h"
|
||||
#include "Support/STLExtras.h"
|
||||
#include "Support/Statistic.h"
|
||||
#include "Support/Debug.h"
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
using namespace llvm;
|
||||
|
@ -37,7 +38,18 @@ static RegisterPass<WriteBytecodePass> X("emitbytecode", "Bytecode Writer");
|
|||
|
||||
static Statistic<>
|
||||
BytesWritten("bytecodewriter", "Number of bytecode bytes written");
|
||||
|
||||
static Statistic<>
|
||||
ConstantTotalBytes("bytecodewriter", "Bytes of constants total");
|
||||
static Statistic<>
|
||||
FunctionConstantTotalBytes("bytecodewriter", "Bytes of function constants total");
|
||||
static Statistic<>
|
||||
ConstantPlaneHeaderBytes("bytecodewriter", "Constant plane header bytes");
|
||||
static Statistic<>
|
||||
InstructionBytes("bytecodewriter", "Bytes of bytes of instructions");
|
||||
static Statistic<>
|
||||
SymTabBytes("bytecodewriter", "Bytes of symbol table");
|
||||
static Statistic<>
|
||||
ModuleInfoBytes("bytecodewriter", "Bytes of module info");
|
||||
|
||||
BytecodeWriter::BytecodeWriter(std::deque<unsigned char> &o, const Module *M)
|
||||
: Out(o), Table(M, true) {
|
||||
|
@ -52,8 +64,9 @@ BytecodeWriter::BytecodeWriter(std::deque<unsigned char> &o, const Module *M)
|
|||
bool hasNoEndianness = M->getEndianness() == Module::AnyEndianness;
|
||||
bool hasNoPointerSize = M->getPointerSize() == Module::AnyPointerSize;
|
||||
|
||||
// Output the version identifier... we are currently on bytecode version #0
|
||||
unsigned Version = (0 << 4) | isBigEndian | (hasLongPointers << 1) |
|
||||
// Output the version identifier... we are currently on bytecode version #1,
|
||||
// which corresponds to LLVM v1.2.
|
||||
unsigned Version = (1 << 4) | isBigEndian | (hasLongPointers << 1) |
|
||||
(hasNoEndianness << 2) | (hasNoPointerSize << 3);
|
||||
output_vbr(Version, Out);
|
||||
align32(Out);
|
||||
|
@ -71,6 +84,12 @@ BytecodeWriter::BytecodeWriter(std::deque<unsigned char> &o, const Module *M)
|
|||
outputConstantsInPlane(Plane, ValNo); // Write out the types
|
||||
}
|
||||
|
||||
DEBUG(for (unsigned i = 0; i != Type::TypeTyID; ++i)
|
||||
if (Table.getPlane(i).size())
|
||||
std::cerr << " ModuleLevel["
|
||||
<< *Type::getPrimitiveType((Type::PrimitiveID)i)
|
||||
<< "] = " << Table.getPlane(i).size() << "\n");
|
||||
|
||||
// The ModuleInfoBlock follows directly after the type information
|
||||
outputModuleInfoBlock(M);
|
||||
|
||||
|
@ -104,6 +123,11 @@ void BytecodeWriter::outputConstantsInPlane(const std::vector<const Value*>
|
|||
NC -= ValNo; // Convert from index into count
|
||||
if (NC == 0) return; // Skip empty type planes...
|
||||
|
||||
// FIXME: Most slabs only have 1 or 2 entries! We should encode this much
|
||||
// more compactly.
|
||||
|
||||
ConstantPlaneHeaderBytes -= Out.size();
|
||||
|
||||
// Output type header: [num entries][type id number]
|
||||
//
|
||||
output_vbr(NC, Out);
|
||||
|
@ -113,6 +137,9 @@ void BytecodeWriter::outputConstantsInPlane(const std::vector<const Value*>
|
|||
assert (Slot != -1 && "Type in constant pool but not in function!!");
|
||||
output_vbr((unsigned)Slot, Out);
|
||||
|
||||
ConstantPlaneHeaderBytes += Out.size();
|
||||
|
||||
|
||||
//cerr << "Emitting " << NC << " constants of type '"
|
||||
// << Plane.front()->getType()->getName() << "' = Slot #" << Slot << "\n";
|
||||
|
||||
|
@ -129,6 +156,8 @@ void BytecodeWriter::outputConstantsInPlane(const std::vector<const Value*>
|
|||
}
|
||||
|
||||
void BytecodeWriter::outputConstants(bool isFunction) {
|
||||
ConstantTotalBytes -= Out.size();
|
||||
if (isFunction) FunctionConstantTotalBytes -= Out.size();
|
||||
BytecodeBlock CPool(BytecodeFormat::ConstantPool, Out);
|
||||
|
||||
unsigned NumPlanes = Table.getNumPlanes();
|
||||
|
@ -160,6 +189,8 @@ void BytecodeWriter::outputConstants(bool isFunction) {
|
|||
outputConstantsInPlane(Plane, ValNo);
|
||||
}
|
||||
}
|
||||
ConstantTotalBytes += Out.size();
|
||||
if (isFunction) FunctionConstantTotalBytes += Out.size();
|
||||
}
|
||||
|
||||
static unsigned getEncodedLinkage(const GlobalValue *GV) {
|
||||
|
@ -174,6 +205,8 @@ static unsigned getEncodedLinkage(const GlobalValue *GV) {
|
|||
}
|
||||
|
||||
void BytecodeWriter::outputModuleInfoBlock(const Module *M) {
|
||||
ModuleInfoBytes -= Out.size();
|
||||
|
||||
BytecodeBlock ModuleInfoBlock(BytecodeFormat::ModuleGlobalInfo, Out);
|
||||
|
||||
// Output the types for the global variables in the module...
|
||||
|
@ -206,6 +239,8 @@ void BytecodeWriter::outputModuleInfoBlock(const Module *M) {
|
|||
output_vbr((unsigned)Table.getSlot(Type::VoidTy), Out);
|
||||
|
||||
align32(Out);
|
||||
|
||||
ModuleInfoBytes += Out.size();
|
||||
}
|
||||
|
||||
void BytecodeWriter::outputFunction(const Function *F) {
|
||||
|
@ -222,10 +257,11 @@ void BytecodeWriter::outputFunction(const Function *F) {
|
|||
|
||||
{ // Output all of the instructions in the body of the function
|
||||
BytecodeBlock ILBlock(BytecodeFormat::InstructionList, Out);
|
||||
|
||||
InstructionBytes -= Out.size();
|
||||
for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E;++BB)
|
||||
for(BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E;++I)
|
||||
processInstruction(*I);
|
||||
InstructionBytes += Out.size();
|
||||
}
|
||||
|
||||
// If needed, output the symbol table for the function...
|
||||
|
@ -240,7 +276,9 @@ void BytecodeWriter::outputSymbolTable(const SymbolTable &MST) {
|
|||
// space!
|
||||
if (MST.begin() == MST.end()) return;
|
||||
|
||||
BytecodeBlock FunctionBlock(BytecodeFormat::SymbolTable, Out);
|
||||
SymTabBytes -= Out.size();
|
||||
|
||||
BytecodeBlock SymTabBlock(BytecodeFormat::SymbolTable, Out);
|
||||
|
||||
for (SymbolTable::const_iterator TI = MST.begin(); TI != MST.end(); ++TI) {
|
||||
SymbolTable::type_const_iterator I = MST.type_begin(TI->first);
|
||||
|
@ -264,6 +302,8 @@ void BytecodeWriter::outputSymbolTable(const SymbolTable &MST) {
|
|||
output(I->first, Out, false); // Don't force alignment...
|
||||
}
|
||||
}
|
||||
|
||||
SymTabBytes += Out.size();
|
||||
}
|
||||
|
||||
void llvm::WriteBytecodeToFile(const Module *C, std::ostream &Out) {
|
||||
|
|
Loading…
Reference in New Issue