blob: fac862dc5235795d3be90e7313cac0201857703e [file] [log] [blame] [edit]
//===- NaClBitcodeDist.cpp --------------------------------------*- C++ -*-===//
// Internal implementation of PNaCl bitcode distributions.
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/Bitcode/NaCl/NaClBitcodeDist.h"
using namespace llvm;
NaClBitcodeDist::~NaClBitcodeDist() {
RemoveCachedDistribution();
for (const_iterator Iter = begin(), IterEnd = end();
Iter != IterEnd; ++Iter) {
delete Iter->second;
}
}
NaClBitcodeDistElement *NaClBitcodeDist::CreateElement(
NaClBitcodeDistValue Value) const {
return Sentinel->CreateElement(Value);
}
void NaClBitcodeDist::GetValueList(const NaClBitcodeRecord &Record,
ValueListType &ValueList) const {
Sentinel->GetValueList(Record, ValueList);
}
void NaClBitcodeDist::AddRecord(const NaClBitcodeRecord &Record) {
if (StorageKind != NaClBitcodeDist::RecordStorage)
return;
ValueListType ValueList;
GetValueList(Record, ValueList);
if (!ValueList.empty()) {
RemoveCachedDistribution();
for (ValueListIterator
Iter = ValueList.begin(),
IterEnd = ValueList.end();
Iter != IterEnd; ++Iter) {
NaClBitcodeDistElement *Element = GetElement(*Iter);
Element->AddRecord(Record);
++Total;
}
}
}
void NaClBitcodeDist::AddBlock(const NaClBitcodeBlock &Block) {
if (StorageKind != NaClBitcodeDist::BlockStorage)
return;
RemoveCachedDistribution();
++Total;
unsigned BlockID = Block.GetBlockID();
NaClBitcodeDistElement *Element = GetElement(BlockID);
Element->AddBlock(Block);
}
void NaClBitcodeDist::Print(raw_ostream &Stream,
const std::string &Indent) const {
const Distribution *Dist = GetDistribution();
Stream << Indent;
Sentinel->PrintTitle(Stream, this);
Stream << Indent;
Sentinel->PrintHeader(Stream);
Stream << "\n";
bool NeedsHeader = false;
for (size_t I = 0, E = Dist->size(); I < E; ++I) {
if (NeedsHeader) {
// Reprint the header so that rows are more readable.
Stream << Indent << " " << Sentinel->GetTitle() << " (continued)\n";
Stream << Indent;
Sentinel->PrintHeader(Stream);
Stream << "\n";
}
const DistPair &Pair = Dist->at(I);
Stream << Indent;
NaClBitcodeDistElement *Element = at(Pair.second);
Element->PrintRow(Stream, Pair.second, this);
NeedsHeader = Element->PrintNestedDistIfApplicable(Stream, Indent);
}
}
void NaClBitcodeDist::Sort() const {
RemoveCachedDistribution();
CachedDistribution = new Distribution();
for (const_iterator Iter = begin(), IterEnd = end();
Iter != IterEnd; ++Iter) {
const NaClBitcodeDistElement *Elmt = Iter->second;
// Only add if histogram element is non-empty.
if (Elmt->GetNumInstances()) {
double Importance = Elmt->GetImportance(Iter->first);
CachedDistribution->push_back(std::make_pair(Importance, Iter->first));
}
}
// Sort in ascending order, based on importance.
std::stable_sort(CachedDistribution->begin(),
CachedDistribution->end());
// Reverse so most important appear first.
std::reverse(CachedDistribution->begin(),
CachedDistribution->end());
}
NaClBitcodeDistElement::~NaClBitcodeDistElement() {}
void NaClBitcodeDistElement::AddRecord(const NaClBitcodeRecord &Record) {
++NumInstances;
}
void NaClBitcodeDistElement::AddBlock(const NaClBitcodeBlock &Block) {
++NumInstances;
}
void NaClBitcodeDistElement::GetValueList(const NaClBitcodeRecord &Record,
ValueListType &ValueList) const {
// By default, assume no record values are defined.
}
double NaClBitcodeDistElement::GetImportance(NaClBitcodeDistValue Value) const {
return static_cast<double>(NumInstances);
}
const char *NaClBitcodeDistElement::GetTitle() const {
return "Distribution";
}
void NaClBitcodeDistElement::
PrintTitle(raw_ostream &Stream, const NaClBitcodeDist *Distribution) const {
Stream << GetTitle() << " (" << Distribution->size() << " elements):\n\n";
}
const char *NaClBitcodeDistElement::GetValueHeader() const {
return "Value";
}
void NaClBitcodeDistElement::PrintStatsHeader(raw_ostream &Stream) const {
Stream << " Count %Count";
}
void NaClBitcodeDistElement::
PrintHeader(raw_ostream &Stream) const {
PrintStatsHeader(Stream);
Stream << " " << GetValueHeader();
}
void NaClBitcodeDistElement::
PrintRowStats(raw_ostream &Stream,
const NaClBitcodeDist *Distribution) const {
unsigned Count = GetNumInstances();
Stream << format("%8d %6.2f",
Count,
(double) Count/Distribution->GetTotal()*100.0);
}
void NaClBitcodeDistElement::
PrintRowValue(raw_ostream &Stream,
NaClBitcodeDistValue Value,
const NaClBitcodeDist *Distribution) const {
std::string ValueFormat;
raw_string_ostream StrStream(ValueFormat);
StrStream << "%" << strlen(GetValueHeader()) << "d";
StrStream.flush();
Stream << format(ValueFormat.c_str(), (int) Value);
}
void NaClBitcodeDistElement::
PrintRow(raw_ostream &Stream,
NaClBitcodeDistValue Value,
const NaClBitcodeDist *Distribution) const {
PrintRowStats(Stream, Distribution);
Stream << " ";
PrintRowValue(Stream, Value, Distribution);
Stream << "\n";
}
const SmallVectorImpl<NaClBitcodeDist*> *NaClBitcodeDistElement::
GetNestedDistributions() const {
return 0;
}
bool NaClBitcodeDistElement::
PrintNestedDistIfApplicable(raw_ostream &Stream,
const std::string &Indent) const {
bool PrintedNestedDists = false;
if (const SmallVectorImpl<NaClBitcodeDist*> *Dists =
GetNestedDistributions()) {
for (SmallVectorImpl<NaClBitcodeDist*>::const_iterator
Iter = Dists->begin(), IterEnd = Dists->end();
Iter != IterEnd; ++Iter) {
NaClBitcodeDist *Dist = *Iter;
if (!Dist->empty()) {
if (!PrintedNestedDists) {
PrintedNestedDists = true;
Stream << "\n";
}
Dist->Print(Stream, Indent + " ");
Stream << "\n";
}
}
}
return PrintedNestedDists;
}