<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>