Skip to content

Commit

Permalink
Re-factor profile writer to separate LLVM and GCC writers.
Browse files Browse the repository at this point in the history
This separates the creation of the profile writers for GCC and LLVM to
minimize the amount of LLVM code that is linked-in to binaries that do
not need to deal with it.

The re-factoring touches quite a bit of code, but there are no
functional changes.
  • Loading branch information
dnovillo committed Mar 25, 2016
1 parent 2157e87 commit 43ada02
Show file tree
Hide file tree
Showing 12 changed files with 159 additions and 1,178 deletions.
28 changes: 12 additions & 16 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@ AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/glog/src
AM_CXXFLAGS = -std=gnu++11

COMMON_PROFILE_CREATOR_FILES = addr2line.cc gcov.cc instruction_map.cc \
llvm_profile_writer.cc module_grouper.cc \
profile_creator.cc profile_writer.cc \
sample_reader.cc source_info.cc symbol_map.cc \
profile.cc
module_grouper.cc profile_creator.cc \
profile_writer.cc sample_reader.cc \
source_info.cc symbol_map.cc profile.cc


bin_PROGRAMS = create_gcov
create_gcov_SOURCES = $(COMMON_PROFILE_CREATOR_FILES) create_gcov.cc
create_gcov_LDADD = $(LLVM_LDFLAGS) libquipper.a libglog.a libsymbolize.a libgflags.a
create_gcov_CXXFLAGS = $(LLVM_CXXFLAGS)
create_gcov_LDADD = libquipper.a libglog.a libsymbolize.a libgflags.a

bin_PROGRAMS += dump_gcov
dump_gcov_SOURCES = profile_reader.cc symbol_map.cc module_grouper.cc gcov.cc \
Expand All @@ -23,30 +21,28 @@ dump_gcov_LDADD = libglog.a libgflags.a libsymbolize.a

bin_PROGRAMS += sample_merger
sample_merger_SOURCES = $(COMMON_PROFILE_CREATOR_FILES) sample_merger.cc
sample_merger_LDADD = $(LLVM_LDFLAGS) libquipper.a libglog.a libsymbolize.a libgflags.a
sample_merger_CXXFLAGS = $(LLVM_CXXFLAGS)
sample_merger_LDADD = libquipper.a libglog.a libsymbolize.a libgflags.a

bin_PROGRAMS += profile_merger
profile_merger_SOURCES = $(COMMON_PROFILE_CREATOR_FILES) profile_reader.cc \
profile_merger.cc
profile_merger_CXXFLAGS = $(LLVM_CXXFLAGS)
profile_merger_LDADD = $(LLVM_LDFLAGS) libquipper.a libglog.a libsymbolize.a libgflags.a
profile_merger_LDADD = libquipper.a libglog.a libsymbolize.a libgflags.a

bin_PROGRAMS += profile_diff
profile_diff_SOURCES = $(COMMON_PROFILE_CREATOR_FILES) profile_reader.cc \
profile_diff.cc
profile_diff_LDADD = $(LLVM_LDFLAGS) libquipper.a libglog.a libsymbolize.a libgflags.a
profile_diff_CXXFLAGS = $(LLVM_CXXFLAGS)
profile_diff_LDADD = libquipper.a libglog.a libsymbolize.a libgflags.a

bin_PROGRAMS += profile_update
profile_update_SOURCES = $(COMMON_PROFILE_CREATOR_FILES) profile_reader.cc \
profile_update.cc
profile_update_LDADD = $(LLVM_LDFLAGS) libquipper.a libglog.a libsymbolize.a libgflags.a
profile_update_CXXFLAGS = $(LLVM_CXXFLAGS)
profile_update_LDADD = libquipper.a libglog.a libsymbolize.a libgflags.a

bin_PROGRAMS += create_llvm_prof
create_llvm_prof_SOURCES = $(COMMON_PROFILE_CREATOR_FILES) create_llvm_prof.cc
create_llvm_prof_LDADD = $(LLVM_LDFLAGS) libquipper.a libglog.a libsymbolize.a libgflags.a
create_llvm_prof_SOURCES = $(COMMON_PROFILE_CREATOR_FILES) \
llvm_profile_writer.cc create_llvm_prof.cc
create_llvm_prof_LDADD = $(LLVM_LDFLAGS) libquipper.a libglog.a libsymbolize.a \
libgflags.a
create_llvm_prof_CXXFLAGS = $(LLVM_CXXFLAGS)

noinst_LIBRARIES = libquipper.a
Expand Down
1,139 changes: 70 additions & 1,069 deletions Makefile.in

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions create_gcov.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "gflags/gflags.h"
#include "profile_creator.h"
#include "gcov.h"

DEFINE_string(profile, "perf.data",
"Profile file name");
Expand All @@ -28,9 +29,10 @@ int main(int argc, char **argv) {
google::ParseCommandLineFlags(&argc, &argv, true);
google::InitGoogleLogging(argv[0]);

autofdo::AutoFDOProfileWriter writer(FLAGS_gcov_version);
autofdo::ProfileCreator creator(FLAGS_binary);
if (creator.CreateProfile(FLAGS_profile, FLAGS_profiler, FLAGS_gcov,
"gcov")) {
if (creator.CreateProfile(FLAGS_profile, FLAGS_profiler, &writer,
FLAGS_gcov)) {
return 0;
} else {
return -1;
Expand Down
13 changes: 9 additions & 4 deletions create_llvm_prof.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@
#include "config.h"

#if defined(HAVE_LLVM)
#include <memory>

#include "gflags/gflags.h"
#include "profile_creator.h"
#include "llvm_profile_writer.h"

DEFINE_string(profile, "perf.data", "Input profile file name");
DEFINE_string(profiler, "perf", "Input profile type");
Expand Down Expand Up @@ -61,18 +64,19 @@ int main(int argc, char **argv) {
return 1;
}

const char *llvm_fmt = nullptr;
std::unique_ptr<autofdo::LLVMProfileWriter> writer(nullptr);
if (FLAGS_format == "text") {
llvm_fmt = "llvm-text";
writer.reset(new autofdo::LLVMProfileWriter(llvm::sampleprof::SPF_Text));
} else if (FLAGS_format == "binary") {
llvm_fmt = "llvm-binary";
writer.reset(new autofdo::LLVMProfileWriter(llvm::sampleprof::SPF_Binary));
} else {
LOG(ERROR) << "--format must be one of 'text' or 'binary'";
return 1;
}

autofdo::ProfileCreator creator(FLAGS_binary);
if (creator.CreateProfile(FLAGS_profile, FLAGS_profiler, FLAGS_out, llvm_fmt))
if (creator.CreateProfile(FLAGS_profile, FLAGS_profiler, writer.get(),
FLAGS_out))
return 0;
else
return -1;
Expand All @@ -85,5 +89,6 @@ int main(int argc, char **argv) {
"ERROR: LLVM support was not enabled in this configuration.\nPlease "
"configure and rebuild with:\n\n$ ./configure "
"--with-llvm=<path-to-llvm-config>\n\n");
return -1;
}
#endif // HAVE_LLVM
9 changes: 7 additions & 2 deletions llvm_profile_writer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "profile_writer.h"

DECLARE_bool(debug_dump);
DECLARE_string(format);

namespace autofdo {

Expand Down Expand Up @@ -81,6 +82,7 @@ void LLVMProfileBuilder::VisitTopSymbol(const string &name,
<< "': " << EC.message();

profile.setName(name_ref);
inline_stack_.clear();
inline_stack_.push_back(&profile);
}

Expand All @@ -89,6 +91,9 @@ void LLVMProfileBuilder::VisitCallsite(const Callsite &callsite) {
uint32 offset = callsite.first;
uint32 line = offset >> 16;
uint32 discriminator = offset & 0xffff;
while (inline_stack_.size() > level_) {
inline_stack_.pop_back();
}
auto &caller_profile = *(inline_stack_.back());
auto &callee_profile =
caller_profile.functionSamplesAt(llvm::sampleprof::LineLocation(
Expand Down Expand Up @@ -148,10 +153,10 @@ bool LLVMProfileWriter::WriteToFile(const string &output_filename) {
// Populate the symbol table. This table contains all the symbols
// for functions found in the binary.
StringIndexMap name_table;
StringTableUpdater::Update(symbol_map_, &name_table);
StringTableUpdater::Update(*symbol_map_, &name_table);

// Gather profiles for all the symbols.
return LLVMProfileBuilder::Write(output_filename, format_, symbol_map_,
return LLVMProfileBuilder::Write(output_filename, format_, *symbol_map_,
name_table);
}

Expand Down
16 changes: 16 additions & 0 deletions llvm_profile_writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,25 @@
#if defined(HAVE_LLVM)
#include "profile_writer.h"
#include "llvm/ProfileData/SampleProf.h"
#include "llvm/ProfileData/SampleProfWriter.h"

namespace autofdo {

// Writer class for LLVM profiles.
class LLVMProfileWriter : public ProfileWriter {
public:
explicit LLVMProfileWriter(
llvm::sampleprof::SampleProfileFormat output_format)
: format_(output_format) {}

bool WriteToFile(const string &output_filename) override;

private:
llvm::sampleprof::SampleProfileFormat format_;

DISALLOW_COPY_AND_ASSIGN(LLVMProfileWriter);
};

class LLVMProfileBuilder : public SymbolTraverser {
public:
explicit LLVMProfileBuilder(const StringIndexMap &name_table)
Expand Down
45 changes: 11 additions & 34 deletions profile_creator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

#include <memory>

#include "config.h"
#include "profile_creator.h"
#include "gflags/gflags.h"
#include "base/common.h"
Expand All @@ -29,10 +28,6 @@
#include "symbolize/elf_reader.h"
#include "module_grouper.h"

#if defined(HAVE_LLVM)
#include "llvm/ProfileData/SampleProfWriter.h"
#endif

namespace autofdo {
uint64 ProfileCreator::GetTotalCountFromTextProfile(
const string &input_profile_name) {
Expand All @@ -45,12 +40,12 @@ uint64 ProfileCreator::GetTotalCountFromTextProfile(

bool ProfileCreator::CreateProfile(const string &input_profile_name,
const string &profiler,
const string &output_profile_name,
const string &output_format) {
ProfileWriter *writer,
const string &output_profile_name) {
if (!ReadSample(input_profile_name, profiler)) {
return false;
}
if (!CreateProfileFromSample(output_profile_name, output_format)) {
if (!CreateProfileFromSample(writer, output_profile_name)) {
return false;
}
return true;
Expand Down Expand Up @@ -105,39 +100,21 @@ bool ProfileCreator::ComputeProfile(SymbolMap *symbol_map,
return true;
}

bool ProfileCreator::CreateProfileFromSample(const string &output_profile_name,
const string &output_format) {
bool ProfileCreator::CreateProfileFromSample(ProfileWriter *writer,
const string &output_name) {
SymbolMap symbol_map(binary_);
Addr2line *addr2line = nullptr;
if (!ComputeProfile(&symbol_map, &addr2line))
return false;
if (!ComputeProfile(&symbol_map, &addr2line)) return false;

ModuleGrouper *grouper = ModuleGrouper::GroupModule(
binary_, GCOV_ELF_SECTION_NAME, &symbol_map);
ModuleGrouper *grouper =
ModuleGrouper::GroupModule(binary_, GCOV_ELF_SECTION_NAME, &symbol_map);

ProfileWriter *writer = nullptr;
if (output_format == "gcov") {
writer = new AutoFDOProfileWriter(symbol_map, grouper->module_map(),
FLAGS_gcov_version);
}
#if defined(HAVE_LLVM)
else if (output_format == "llvm-text") {
writer = new LLVMProfileWriter(symbol_map, grouper->module_map(),
llvm::sampleprof::SPF_Text);
} else if (output_format == "llvm-binary") {
writer = new LLVMProfileWriter(symbol_map, grouper->module_map(),
llvm::sampleprof::SPF_Binary);
}
#endif
else {
LOG(ERROR) << "Unsupported output profile format: " << output_format;
return false;
}
writer->setSymbolMap(&symbol_map);
writer->setModuleMap(&grouper->module_map());
bool ret = writer->WriteToFile(output_name);

bool ret = writer->WriteToFile(output_profile_name);
delete addr2line;
delete grouper;
delete writer;
return ret;
}

Expand Down
12 changes: 6 additions & 6 deletions profile_creator.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "addr2line.h"
#include "sample_reader.h"
#include "symbol_map.h"
#include "profile_writer.h"

namespace autofdo {

Expand All @@ -36,18 +37,17 @@ class ProfileCreator {
static uint64 GetTotalCountFromTextProfile(const string &input_profile_name);

// Creates AutoFDO profile, returns true if success, false otherwise.
bool CreateProfile(const string &input_profile_name,
const string &profiler,
const string &output_profile_name,
const string &output_format);
bool CreateProfile(const string &input_profile_name, const string &profiler,
autofdo::ProfileWriter *writer,
const string &output_profile_name);

// Reads samples from the input profile.
bool ReadSample(const string &input_profile_name,
const string &profiler);

// Creates output profile after reading from the input profile.
bool CreateProfileFromSample(const string &output_profile_name,
const string &output_format);
bool CreateProfileFromSample(autofdo::ProfileWriter *writer,
const string &output_name);

// Returns total number of samples collected.
uint64 TotalSamples();
Expand Down
4 changes: 2 additions & 2 deletions profile_merger.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ int main(int argc, char **argv) {
}

symbol_map.CalculateThreshold();
autofdo::AutoFDOProfileWriter writer(symbol_map,
module_map, FLAGS_gcov_version);
autofdo::AutoFDOProfileWriter writer(&symbol_map, &module_map,
FLAGS_gcov_version);
if (!writer.WriteToFile(FLAGS_output_file)) {
LOG(FATAL) << "Error writing to " << FLAGS_output_file;
}
Expand Down
4 changes: 2 additions & 2 deletions profile_update.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ int main(int argc, char **argv) {
ModuleGrouper *grouper = ModuleGrouper::GroupModule(
FLAGS_binary, GCOV_ELF_SECTION_NAME, &symbol_map);

AutoFDOProfileWriter writer(symbol_map,
grouper->module_map(), FLAGS_gcov_version);
AutoFDOProfileWriter writer(&symbol_map, &grouper->module_map(),
FLAGS_gcov_version);
if (!writer.WriteToFile(FLAGS_output)) {
LOG(FATAL) << "Error writing to " << FLAGS_output;
}
Expand Down
19 changes: 9 additions & 10 deletions profile_writer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ void AutoFDOProfileWriter::WriteFunctionProfile() {
int length_4bytes = 0, current_name_index = 0;
string_index_map[string()] = 0;

StringTableUpdater::Update(symbol_map_, &string_index_map);
StringTableUpdater::Update(*symbol_map_, &string_index_map);

for (auto &name_index : string_index_map) {
name_index.second = current_name_index++;
Expand Down Expand Up @@ -186,11 +186,11 @@ void AutoFDOProfileWriter::WriteFunctionProfile() {
}

// Compute the length of the GCOV_TAG_AFDO_FUNCTION section.
SourceProfileLengther length(symbol_map_);
SourceProfileLengther length(*symbol_map_);
gcov_write_unsigned(GCOV_TAG_AFDO_FUNCTION);
gcov_write_unsigned(length.length() + 1);
gcov_write_unsigned(length.num_functions());
SourceProfileWriter::Write(symbol_map_, string_index_map);
SourceProfileWriter::Write(*symbol_map_, string_index_map);
}

void AutoFDOProfileWriter::WriteModuleGroup() {
Expand All @@ -205,7 +205,7 @@ void AutoFDOProfileWriter::WriteModuleGroup() {
// cpp_defines_size, cpp_includes_size,
// cl_args_size
static const uint32 MODULE_AUX_DATA_SIZE_IN_4BYTES = 9;
for (const auto &module_aux : module_map_) {
for (const auto &module_aux : *module_map_) {
if (!module_aux.second.is_exported
&& module_aux.second.aux_modules.size() == 0) {
continue;
Expand Down Expand Up @@ -237,7 +237,7 @@ void AutoFDOProfileWriter::WriteModuleGroup() {
// Writes to .afdo file and .afdo.imports file.
gcov_write_unsigned(length_4bytes);
gcov_write_unsigned(num_modules);
for (const auto &module_aux : module_map_) {
for (const auto &module_aux : *module_map_) {
if (!module_aux.second.is_exported
&& module_aux.second.aux_modules.size() == 0) {
continue;
Expand Down Expand Up @@ -310,7 +310,7 @@ void AutoFDOProfileWriter::WriteModuleGroup() {
void AutoFDOProfileWriter::WriteWorkingSet() {
gcov_write_unsigned(GCOV_TAG_AFDO_WORKING_SET);
gcov_write_unsigned(3 * NUM_GCOV_WORKING_SETS);
const gcov_working_set_info *working_set = symbol_map_.GetWorkingSets();
const gcov_working_set_info *working_set = symbol_map_->GetWorkingSets();
for (int i = 0; i < NUM_GCOV_WORKING_SETS; i++) {
gcov_write_unsigned(working_set[i].num_counters / WORKING_SET_INSN_PER_BB);
gcov_write_counter(working_set[i].min_counter);
Expand All @@ -330,7 +330,6 @@ bool AutoFDOProfileWriter::WriteToFile(const string &output_filename) {
return true;
}


// Debugging support. ProfileDumper emits a detailed dump of the contents
// of the input profile.
class ProfileDumper : public SymbolTraverser {
Expand Down Expand Up @@ -451,11 +450,11 @@ class ProfileDumper : public SymbolTraverser {
// Emit a dump of the input profile on stdout.
void ProfileWriter::Dump() {
StringIndexMap string_index_map;
StringTableUpdater::Update(symbol_map_, &string_index_map);
SourceProfileLengther length(symbol_map_);
StringTableUpdater::Update(*symbol_map_, &string_index_map);
SourceProfileLengther length(*symbol_map_);
printf("Length of symbol map: %d\n", length.length() + 1);
printf("Number of functions: %d\n", length.num_functions());
ProfileDumper::Write(symbol_map_, string_index_map);
ProfileDumper::Write(*symbol_map_, string_index_map);
}

} // namespace autofdo
Loading

0 comments on commit 43ada02

Please sign in to comment.