<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Sep 25, 2013 at 8:18 PM, Eric Christopher <span dir="ltr"><<a href="mailto:echristo@gmail.com" target="_blank">echristo@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im">On Wed, Sep 25, 2013 at 9:11 AM, Evan Cheng <<a href="mailto:evan.cheng@apple.com">evan.cheng@apple.com</a>> wrote:<br>

> Hi Diego,<br>
><br>
> I am curious. Why is this called automatic PGO? Why is it automatic?<br>
<br>
</div>Because it doesn't require instrumentation. :)<br>
<br>
Better names welcome. Maybe "sample pgo"? *shrug* Auto just sounds cooler.<br></blockquote><div><br></div><div>pmu-pgo? </div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<span class="HOEnZb"><font color="#888888"><br>
-eric<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
><br>
> Also, why is the auto-profile part done as a scalar transformation pass? Did you consider alternatives?<br>
><br>
> Thanks,<br>
><br>
> Evan<br>
><br>
> Sent from my iPad<br>
><br>
>> On Sep 24, 2013, at 7:07 AM, Diego Novillo <<a href="mailto:dnovillo@google.com">dnovillo@google.com</a>> wrote:<br>
>><br>
>> This adds two options: -auto-profile and -auto-profile-file. The new<br>
>> option causes the compiler to read a profile file and emit IR<br>
>> metadata reflecting that profile.<br>
>><br>
>> The profile file is assumed to have been generated by an external<br>
>> profile source. The profile information is converted into IR metadata,<br>
>> which is later used by the analysis routines to estimate block<br>
>> frequencies, edge weights and other related data.<br>
>><br>
>> External profile information files have no fixed format, each profiler<br>
>> is free to define its own. This includes both the on-disk representation<br>
>> of the profile and the kind of profile information stored in the file.<br>
>> A common kind of profile is based on sampling (e.g., perf), which<br>
>> essentially counts how many times each line of the program has been<br>
>> executed during the run.<br>
>><br>
>> The only requirements is that each profiler must provide a way to<br>
>> load its own profile format into internal data structures and<br>
>> then a method to convert that data into IR annotations.<br>
>><br>
>> The AutoProfile pass is organized as a scalar transformation. On<br>
>> startup, it reads the file given in -auto-profile-file to determine what<br>
>> kind of profile it contains.  This file is assumed to contain profile<br>
>> information for the whole application. The profile data in the file is<br>
>> read and incorporated into the internal state of the corresponding<br>
>> profiler.<br>
>><br>
>> To facilitate testing, I've organized the profilers to support two file<br>
>> formats: text and native. The native format is whatever on-disk<br>
>> representation the profiler wants to support, I think this will mostly<br>
>> be bitcode files, but it could be anything the profiler wants to<br>
>> support. To do this, every profiler must implement the<br>
>> AutoProfiler::loadNative() function.<br>
>><br>
>> The text format is mostly meant for debugging. Records are separated by<br>
>> newlines, but each profiler is free to interpret records as it sees fit.<br>
>> Profilers must implement the AutoProfiler::loadText() function.<br>
>><br>
>> Finally, the pass will call AutoProfiler::emitAnnotations() for each<br>
>> function in the current translation unit. This function needs to<br>
>> translate the loaded profile into IR metadata, which the analyzer will<br>
>> later be able to use.<br>
>><br>
>> This patch implements the first steps towards the above design. I've<br>
>> implemented a sample-based flat profiler. The format of the profile is<br>
>> fairly simplistic. Each sampled function contains a list of relative<br>
>> line locations (from the start of the function) together with a count<br>
>> representing how many samples were collected at that line during<br>
>> execution. I generate this profile using perf and a separate converter<br>
>> tool.<br>
>><br>
>> Currently, I have only implemented a text format for these profiles. I<br>
>> am interested in initial feedback to the whole approach before I send<br>
>> the other parts of the implementation for review.<br>
>><br>
>> This patch implements:<br>
>><br>
>> - The AutoProfile pass.<br>
>> - The base AutoProfiler class with the core interface.<br>
>> - A SampleBasedProfiler using the above interface. The profiler<br>
>>  generates metadata autoprofile.samples on every IR instruction that<br>
>>  matches the profiles.<br>
>> - A text loader class to assist the implementation of<br>
>>  AutoProfiler::loadText().<br>
>><br>
>> Caveats and questions:<br>
>><br>
>> 1- I am almost certainly using the wrong APIs or using the right<br>
>>   APIs in unorthodox ways. Please point me to better<br>
>>   alternatives.<br>
>><br>
>> 2- I was surprised to learn that line number information is not<br>
>>   transferred into the IR unless we are emitting debug<br>
>>   information. For sample-based profiling, I'm going to need<br>
>>   line number information generated by the front-end<br>
>>   independently of debug info. Eric, is that possible?<br>
>><br>
>> 3- I have not included in this patch changes to the analyzer. I<br>
>>   want to keep it focused to the profile loading and IR<br>
>>   annotation. In the analyzer, we will have propagation of<br>
>>   attributes and other fixes (e.g., from the samples it is<br>
>>   possible to have instructions on the same basic block<br>
>>   registered with differing number of samples). I also have not<br>
>>   included changes to code motion to get rid of the autoprofile<br>
>>   information.<br>
>><br>
>> 4- I need to add test cases.<br>
>><br>
>> Mainly, I'm interested in making sure that this direction is<br>
>> generally useful. I haven't given a lot of thought to other types<br>
>> of profiling, but I'm certain any kind of tracing or other<br>
>> execution frequency profiles can be adapted. Things like value<br>
>> profiling may be a bit more involved, but mostly because I'm not<br>
>> sure how the type and symbols are tracked in LLVM.<br>
>><br>
>> Thanks.  Diego.<br>
>> ---<br>
>> include/llvm/InitializePasses.h       |   1 +<br>
>> include/llvm/Transforms/Scalar.h      |   6 +<br>
>> lib/Transforms/Scalar/AutoProfile.cpp | 363 ++++++++++++++++++++++++++++++++++<br>
>> lib/Transforms/Scalar/CMakeLists.txt  |   1 +<br>
>> lib/Transforms/Scalar/Scalar.cpp      |   1 +<br>
>> 5 files changed, 372 insertions(+)<br>
>> create mode 100644 lib/Transforms/Scalar/AutoProfile.cpp<br>
>><br>
>> diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h<br>
>> index 1b50bb2..c922228 100644<br>
>> --- a/include/llvm/InitializePasses.h<br>
>> +++ b/include/llvm/InitializePasses.h<br>
>> @@ -70,6 +70,7 @@ void initializeAliasDebuggerPass(PassRegistry&);<br>
>> void initializeAliasSetPrinterPass(PassRegistry&);<br>
>> void initializeAlwaysInlinerPass(PassRegistry&);<br>
>> void initializeArgPromotionPass(PassRegistry&);<br>
>> +void initializeAutoProfilePass(PassRegistry&);<br>
>> void initializeBarrierNoopPass(PassRegistry&);<br>
>> void initializeBasicAliasAnalysisPass(PassRegistry&);<br>
>> void initializeBasicCallGraphPass(PassRegistry&);<br>
>> diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h<br>
>> index 51aeba4..9ee5b49 100644<br>
>> --- a/include/llvm/Transforms/Scalar.h<br>
>> +++ b/include/llvm/Transforms/Scalar.h<br>
>> @@ -354,6 +354,12 @@ FunctionPass *createLowerExpectIntrinsicPass();<br>
>> //<br>
>> FunctionPass *createPartiallyInlineLibCallsPass();<br>
>><br>
>> +//===----------------------------------------------------------------------===//<br>
>> +//<br>
>> +// AutoProfilePass - Loads profile data from disk and generates<br>
>> +// IR metadata to reflect the profile.<br>
>> +FunctionPass *createAutoProfilePass();<br>
>> +<br>
>> } // End llvm namespace<br>
>><br>
>> #endif<br>
>> diff --git a/lib/Transforms/Scalar/AutoProfile.cpp b/lib/Transforms/Scalar/AutoProfile.cpp<br>
>> new file mode 100644<br>
>> index 0000000..7a63409<br>
>> --- /dev/null<br>
>> +++ b/lib/Transforms/Scalar/AutoProfile.cpp<br>
>> @@ -0,0 +1,363 @@<br>
>> +//===- AutoProfile.cpp - Incorporate an external profile into the IR ------===//<br>
>> +//<br>
>> +//                      The LLVM Compiler Infrastructure<br>
>> +//<br>
>> +// This file is distributed under the University of Illinois Open Source<br>
>> +// License. See LICENSE.TXT for details.<br>
>> +//<br>
>> +//===----------------------------------------------------------------------===//<br>
>> +//<br>
>> +// This file implements the Auto Profile transformation. This pass reads a<br>
>> +// profile file generated by an external profiling source and generates IR<br>
>> +// metadata to reflect the profile information in the given profile.<br>
>> +//<br>
>> +// TODO(dnovillo) Add more.<br>
>> +//<br>
>> +//===----------------------------------------------------------------------===//<br>
>> +<br>
>> +#define DEBUG_TYPE "auto-profile"<br>
>> +<br>
>> +#include <cstdlib><br>
>> +<br>
>> +#include "llvm/ADT/DenseMap.h"<br>
>> +#include "llvm/ADT/OwningPtr.h"<br>
>> +#include "llvm/ADT/StringMap.h"<br>
>> +#include "llvm/DebugInfo/DIContext.h"<br>
>> +#include "llvm/IR/Constants.h"<br>
>> +#include "llvm/IR/Function.h"<br>
>> +#include "llvm/IR/Instructions.h"<br>
>> +#include "llvm/IR/LLVMContext.h"<br>
>> +#include "llvm/IR/Metadata.h"<br>
>> +#include "llvm/IR/Module.h"<br>
>> +#include "llvm/Pass.h"<br>
>> +#include "llvm/Support/CommandLine.h"<br>
>> +#include "llvm/Support/Debug.h"<br>
>> +#include "llvm/Support/InstIterator.h"<br>
>> +#include "llvm/Support/MemoryBuffer.h"<br>
>> +#include "llvm/Support/Regex.h"<br>
>> +#include "llvm/Support/raw_ostream.h"<br>
>> +#include "llvm/Transforms/Scalar.h"<br>
>> +<br>
>> +using namespace llvm;<br>
>> +<br>
>> +// command line option for loading path profiles<br>
>> +static cl::opt<std::string> AutoProfileFilename(<br>
>> +    "auto-profile-file", cl::init("autoprof.llvm"), cl::value_desc("filename"),<br>
>> +    cl::desc("Profile file loaded by -auto-profile"), cl::Hidden);<br>
>> +<br>
>> +namespace {<br>
>> +<br>
>> +// Base profiler abstract class. This defines the abstract interface<br>
>> +// that every profiler should respond to.<br>
>> +//<br>
>> +// TODO(dnovillo) - Eventually this class ought to move to a separate file.<br>
>> +// There will be several types of profile loaders. Having them all together in<br>
>> +// this file will get pretty messy.<br>
>> +class AutoProfiler {<br>
>> +public:<br>
>> +  AutoProfiler(std::string filename) : filename_(filename) {}<br>
>> +  ~AutoProfiler() {}<br>
>> +<br>
>> +  // Load the profile from a file in the native format of this profile.<br>
>> +  virtual bool loadNative() = 0;<br>
>> +<br>
>> +  // Load the profile from a text file.<br>
>> +  virtual bool loadText() = 0;<br>
>> +<br>
>> +  // Dump this profile on stderr.<br>
>> +  virtual void dump() = 0;<br>
>> +<br>
>> +  // Modify the IR with annotations corresponding to the loaded profile.<br>
>> +  virtual bool emitAnnotations(Function &F) = 0;<br>
>> +<br>
>> +  // Instantiate an auto-profiler object based on the detected format of the<br>
>> +  // give file name. Set *is_text to true, if the file is in text format.<br>
>> +  static AutoProfiler *<br>
>> +  instantiateProfiler(const std::string filename, bool *is_text);<br>
>> +<br>
>> +protected:<br>
>> +  // Path name to the file holding the profile data.<br>
>> +  std::string filename_;<br>
>> +};<br>
>> +<br>
>> +<br>
>> +// Sample-based profiler. These profiles contain execution frequency<br>
>> +// information on the function bodies of the program.<br>
>> +class AutoProfileSampleBased : public AutoProfiler {<br>
>> +public:<br>
>> +  AutoProfileSampleBased(std::string filename)<br>
>> +      : AutoProfiler(filename), profiles_(0) {}<br>
>> +<br>
>> +  // Metadata kind for autoprofile.samples.<br>
>> +  static unsigned AutoProfileSamplesMDKind;<br>
>> +<br>
>> +  virtual void dump();<br>
>> +  virtual bool loadText();<br>
>> +  virtual bool loadNative() { llvm_unreachable("not implemented"); }<br>
>> +  virtual bool emitAnnotations(Function &F);<br>
>> +<br>
>> +  void dumpFunctionProfile(StringRef fn_name);<br>
>> +<br>
>> +protected:<br>
>> +  typedef DenseMap<uint32_t, uint32_t> BodySampleMap;<br>
>> +<br>
>> +  struct FunctionProfile {<br>
>> +    // Total number of samples collected inside this function. Samples<br>
>> +    // are cumulative, they include all the samples collected inside<br>
>> +    // this function and all its inlined callees.<br>
>> +    unsigned TotalSamples;<br>
>> +<br>
>> +    // Total number of samples collected at the head of the function.<br>
>> +    unsigned TotalHeadSamples;<br>
>> +<br>
>> +    // Map <line offset, samples> of line offset to samples collected<br>
>> +    // inside the function. Each entry in this map contains the number<br>
>> +    // of samples collected at the corresponding line offset. All line<br>
>> +    // locations are an offset from the start of the function.<br>
>> +    BodySampleMap BodySamples;<br>
>> +  };<br>
>> +<br>
>> +  typedef StringMap<FunctionProfile> FunctionProfileMap;<br>
>> +<br>
>> +  FunctionProfileMap profiles_;<br>
>> +};<br>
>> +<br>
>> +// Loader class for text-based profiles. These are mostly useful to<br>
>> +// generate unit tests and not much else.<br>
>> +class AutoProfileTextLoader {<br>
>> +public:<br>
>> +  AutoProfileTextLoader(std::string filename) : filename_(filename) {<br>
>> +    error_code ec;<br>
>> +    ec = MemoryBuffer::getFile(filename_, buffer_);<br>
>> +    if (ec)<br>
>> +      report_fatal_error("Could not open profile file " + filename_ + ": " +<br>
>> +                         ec.message());<br>
>> +    fp_ = buffer_->getBufferStart();<br>
>> +    linenum_ = 0;<br>
>> +  }<br>
>> +<br>
>> +  // Read a line from the mapped file. Update the current line and file pointer.<br>
>> +  StringRef readLine() {<br>
>> +    size_t length = 0;<br>
>> +    const char *start = fp_;<br>
>> +    while (fp_ != buffer_->getBufferEnd() && *fp_ != '\n') {<br>
>> +      length++;<br>
>> +      fp_++;<br>
>> +    }<br>
>> +    if (fp_ != buffer_->getBufferEnd())<br>
>> +      fp_++;<br>
>> +    linenum_++;<br>
>> +    return StringRef(start, length);<br>
>> +  }<br>
>> +<br>
>> +  // Return true, if we've reached EOF.<br>
>> +  bool atEOF() const {<br>
>> +    return fp_ == buffer_->getBufferEnd();<br>
>> +  }<br>
>> +<br>
>> +  void reportParseError(std::string msg) const {<br>
>> +    // TODO(dnovillo) - This is almost certainly the wrong way to emit<br>
>> +    // diagnostics and exit the compiler.<br>
>> +    errs() << filename_ << ":" << linenum_ << ": " << msg << "\n";<br>
>> +    exit(1);<br>
>> +  }<br>
>> +<br>
>> +private:<br>
>> +  OwningPtr<MemoryBuffer> buffer_;<br>
>> +  const char *fp_;<br>
>> +  size_t linenum_;<br>
>> +  std::string filename_;<br>
>> +};<br>
>> +<br>
>> +// Auto profile pass. This pass reads profile data from the file specified<br>
>> +// by -auto-profile-file and annotates every affected function with the<br>
>> +// profile information found in that file.<br>
>> +class AutoProfile : public FunctionPass {<br>
>> +public:<br>
>> +  // Class identification, replacement for typeinfo<br>
>> +  static char ID;<br>
>> +<br>
>> +  AutoProfile() : FunctionPass(ID), profiler_(0) {<br>
>> +    initializeAutoProfilePass(*PassRegistry::getPassRegistry());<br>
>> +  }<br>
>> +<br>
>> +  virtual bool doInitialization(Module &M);<br>
>> +<br>
>> +  ~AutoProfile() { delete profiler_; }<br>
>> +<br>
>> +  void dump() { profiler_->dump(); }<br>
>> +<br>
>> +  virtual const char *getPassName() const {<br>
>> +    return "Auto profile pass";<br>
>> +  }<br>
>> +<br>
>> +  virtual bool runOnFunction(Function &F);<br>
>> +<br>
>> +  virtual void getAnalysisUsage(AnalysisUsage &AU) const {<br>
>> +    AU.setPreservesCFG();<br>
>> +  }<br>
>> +<br>
>> +  bool loadProfile();<br>
>> +<br>
>> +protected:<br>
>> +  AutoProfiler *profiler_;<br>
>> +};<br>
>> +}<br>
>> +<br>
>> +// Dump the sample profile for the given function.<br>
>> +void AutoProfileSampleBased::dumpFunctionProfile(StringRef fn_name) {<br>
>> +  FunctionProfile fn_profile = profiles_[fn_name];<br>
>> +  errs() << "Function: " << fn_name << ", " << fn_profile.TotalSamples << ", "<br>
>> +         << fn_profile.TotalHeadSamples << ", " << fn_profile.BodySamples.size()<br>
>> +         << " sampled lines\n";<br>
>> +  for (BodySampleMap::const_iterator si = fn_profile.BodySamples.begin();<br>
>> +       si != fn_profile.BodySamples.end(); si++)<br>
>> +    errs() << "\tline offset: " << si->first<br>
>> +           << ", number of samples: " << si->second << "\n";<br>
>> +  errs() << "\n";<br>
>> +}<br>
>> +<br>
>> +// Dump all the collected function profiles.<br>
>> +void AutoProfileSampleBased::dump() {<br>
>> +  FunctionProfileMap::const_iterator it;<br>
>> +  for (it = profiles_.begin(); it != profiles_.end(); it++)<br>
>> +    dumpFunctionProfile(it->getKey());<br>
>> +}<br>
>> +<br>
>> +// Load a sample profile from a text file.<br>
>> +bool AutoProfileSampleBased::loadText() {<br>
>> +  AutoProfileTextLoader loader(filename_);<br>
>> +<br>
>> +  // Read the symbol table.<br>
>> +  std::string line = loader.readLine().str();<br>
>> +  if (line != "symbol table")<br>
>> +    loader.reportParseError("Expected 'symbol table', found " + line);<br>
>> +  Regex num("[0-9]+");<br>
>> +  line = loader.readLine().str();<br>
>> +  if (!num.match(line))<br>
>> +    loader.reportParseError("Expected a number, found " + line);<br>
>> +  int num_symbols = atoi(line.c_str());<br>
>> +  for (int i = 0; i < num_symbols; i++) {<br>
>> +    StringRef fn_name = loader.readLine();<br>
>> +    FunctionProfile &fn_profile = profiles_[fn_name];<br>
>> +    fn_profile.BodySamples.clear();<br>
>> +    fn_profile.TotalSamples = 0;<br>
>> +    fn_profile.TotalHeadSamples = 0;<br>
>> +  }<br>
>> +<br>
>> +  // Read the profile of each function. Since each function may be<br>
>> +  // mentioned more than once, and we are collecting flat profiles,<br>
>> +  // accumulate samples as we parse them.<br>
>> +  while (!loader.atEOF()) {<br>
>> +    SmallVector<StringRef, 4> matches;<br>
>> +    Regex head_re("^([^:]+):([0-9]+):([0-9]+):([0-9]+)$");<br>
>> +    line = loader.readLine().str();<br>
>> +    if (!head_re.match(line, &matches))<br>
>> +      loader.reportParseError("Expected 'mangled_name:NUM:NUM:NUM', found " +<br>
>> +                              line);<br>
>> +    assert(matches.size() == 5);<br>
>> +    StringRef fn_name = matches[1];<br>
>> +    unsigned num_samples = atoi(matches[2].str().c_str());<br>
>> +    unsigned num_head_samples = atoi(matches[3].str().c_str());<br>
>> +    unsigned num_sampled_lines = atoi(matches[4].str().c_str());<br>
>> +    FunctionProfile &fn_profile = profiles_[fn_name];<br>
>> +    fn_profile.TotalSamples += num_samples;<br>
>> +    fn_profile.TotalHeadSamples += num_head_samples;<br>
>> +    BodySampleMap &sample_map = fn_profile.BodySamples;<br>
>> +    unsigned i;<br>
>> +    for (i = 0; i < num_sampled_lines && !loader.atEOF(); i++) {<br>
>> +      Regex line_sample("^([0-9]+): ([0-9]+)$");<br>
>> +      line = loader.readLine().str();<br>
>> +      if (!line_sample.match(line, &matches))<br>
>> +        loader.reportParseError("Expected 'NUM: NUM', found " + line);<br>
>> +      assert(matches.size() == 3);<br>
>> +      unsigned line_offset = atoi(matches[1].str().c_str());<br>
>> +      unsigned num_samples = atoi(matches[2].str().c_str());<br>
>> +      sample_map[line_offset] += num_samples;<br>
>> +    }<br>
>> +<br>
>> +    if (i < num_sampled_lines)<br>
>> +      loader.reportParseError("Unexpected end of file");<br>
>> +  }<br>
>> +<br>
>> +  return true;<br>
>> +}<br>
>> +<br>
>> +// Annotate function F with the contents of the profile.<br>
>> +bool AutoProfileSampleBased::emitAnnotations(Function &F) {<br>
>> +  bool changed = false;<br>
>> +  StringRef name = F.getName();<br>
>> +  FunctionProfile &fn_profile = profiles_[name];<br>
>> +  BodySampleMap &body_samples = fn_profile.BodySamples;<br>
>> +  Instruction &first_inst = *(inst_begin(F));<br>
>> +  unsigned first_line = first_inst.getDebugLoc().getLine();<br>
>> +  LLVMContext &context = first_inst.getContext();<br>
>> +  for (inst_iterator i = inst_begin(F); i != inst_end(F); ++i) {<br>
>> +    Instruction &inst = *i;<br>
>> +    const DebugLoc &dloc = inst.getDebugLoc();<br>
>> +    unsigned loc_offset = dloc.getLine() - first_line + 1;<br>
>> +    if (body_samples.find(loc_offset) != body_samples.end()) {<br>
>> +      SmallVector<Value *, 1> sample_values;<br>
>> +      sample_values.push_back(ConstantInt::get(Type::getInt32Ty(context),<br>
>> +                                               body_samples[loc_offset]));<br>
>> +      MDNode *md = MDNode::get(context, sample_values);<br>
>> +      inst.setMetadata(AutoProfileSamplesMDKind, md);<br>
>> +      changed = true;<br>
>> +    }<br>
>> +  }<br>
>> +<br>
>> +  DEBUG(if (changed) {<br>
>> +              dbgs() << "\n\nInstructions changed in " << name << "\n";<br>
>> +              for (inst_iterator i = inst_begin(F); i != inst_end(F); ++i) {<br>
>> +                Instruction &inst = *i;<br>
>> +                MDNode *md = inst.getMetadata(AutoProfileSamplesMDKind);<br>
>> +                if (md) {<br>
>> +                  assert(md->getNumOperands() == 1);<br>
>> +                  ConstantInt *val = dyn_cast<ConstantInt>(md->getOperand(0));<br>
>> +                  dbgs() << inst << " (" << val->getValue().getZExtValue()<br>
>> +                         << " samples)\n";<br>
>> +                }<br>
>> +              }<br>
>> +            });<br>
>> +<br>
>> +  return changed;<br>
>> +}<br>
>> +<br>
>> +AutoProfiler *AutoProfiler::instantiateProfiler(const std::string filename,<br>
>> +                                                bool *is_text) {<br>
>> +  // TODO(dnovillo) - Implement file type detection and return the appropriate<br>
>> +  // AutoProfiler sub-class instance.<br>
>> +  *is_text = true;<br>
>> +  return new AutoProfileSampleBased(filename);<br>
>> +}<br>
>> +<br>
>> +unsigned AutoProfileSampleBased::AutoProfileSamplesMDKind = 0;<br>
>> +char AutoProfile::ID = 0;<br>
>> +INITIALIZE_PASS(AutoProfile, "auto-profile", "Auto Profile loader", false,<br>
>> +                false)<br>
>> +<br>
>> +bool AutoProfile::runOnFunction(Function& F) {<br>
>> +  return profiler_->emitAnnotations(F);<br>
>> +}<br>
>> +<br>
>> +bool AutoProfile::loadProfile() {<br>
>> +  bool is_text;<br>
>> +  profiler_ =<br>
>> +      AutoProfiler::instantiateProfiler(AutoProfileFilename, &is_text);<br>
>> +  if (!profiler_)<br>
>> +    return false;<br>
>> +<br>
>> +  return (is_text) ? profiler_->loadText() : profiler_->loadNative();<br>
>> +}<br>
>> +<br>
>> +bool AutoProfile::doInitialization(Module &M) {<br>
>> +  if (!loadProfile())<br>
>> +    return false;<br>
>> +  AutoProfileSampleBased::AutoProfileSamplesMDKind =<br>
>> +      M.getContext().getMDKindID("autoprofile.samples");<br>
>> +  return true;<br>
>> +}<br>
>> +<br>
>> +FunctionPass *llvm::createAutoProfilePass() {<br>
>> +  return new AutoProfile();<br>
>> +}<br>
>> diff --git a/lib/Transforms/Scalar/CMakeLists.txt b/lib/Transforms/Scalar/CMakeLists.txt<br>
>> index 3b89fd4..1093ef0 100644<br>
>> --- a/lib/Transforms/Scalar/CMakeLists.txt<br>
>> +++ b/lib/Transforms/Scalar/CMakeLists.txt<br>
>> @@ -1,5 +1,6 @@<br>
>> add_llvm_library(LLVMScalarOpts<br>
>>   ADCE.cpp<br>
>> +  AutoProfile.cpp<br>
>>   CodeGenPrepare.cpp<br>
>>   ConstantProp.cpp<br>
>>   CorrelatedValuePropagation.cpp<br>
>> diff --git a/lib/Transforms/Scalar/Scalar.cpp b/lib/Transforms/Scalar/Scalar.cpp<br>
>> index 0c3ffbc..542aa33 100644<br>
>> --- a/lib/Transforms/Scalar/Scalar.cpp<br>
>> +++ b/lib/Transforms/Scalar/Scalar.cpp<br>
>> @@ -28,6 +28,7 @@ using namespace llvm;<br>
>> /// ScalarOpts library.<br>
>> void llvm::initializeScalarOpts(PassRegistry &Registry) {<br>
>>   initializeADCEPass(Registry);<br>
>> +  initializeAutoProfilePass(Registry);<br>
>>   initializeCodeGenPreparePass(Registry);<br>
>>   initializeConstantPropagationPass(Registry);<br>
>>   initializeCorrelatedValuePropagationPass(Registry);<br>
>> --<br>
>> 1.8.4<br>
>><br>
>> _______________________________________________<br>
>> llvm-commits mailing list<br>
>> <a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
>> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
> _______________________________________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</div></div></blockquote></div><br></div></div>