[llvm] r247874 - GCC AutoFDO profile reader - Initial support.
Dehao Chen via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 16 17:43:34 PDT 2015
Module is only useful for LIPO, so I guess LLVM can just ignore this
part. I don't think workset is implemented in llvm. So I think it's OK
to ignore them for now too.
Dehao
On Wed, Sep 16, 2015 at 5:40 PM, Diego Novillo <dnovillo at google.com> wrote:
> Dehao,
>
> I'm not sure how important it is to support modules and working sets for
> LLVM's variant of AutoFDO. I will be implementing the inline stack
> traversal support in the next few patches. Do you think we'll need the
> other two?
>
>
> Thanks.
>
> On Wed, Sep 16, 2015 at 8:17 PM, Diego Novillo via llvm-commits
> <llvm-commits at lists.llvm.org> wrote:
>>
>> Author: dnovillo
>> Date: Wed Sep 16 19:17:24 2015
>> New Revision: 247874
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=247874&view=rev
>> Log:
>> GCC AutoFDO profile reader - Initial support.
>>
>> This adds enough machinery to support reading simple GCC AutoFDO
>> profiles. It now supports reading flat profiles (no function calls).
>> Subsequent patches will add support for:
>>
>> - Inlined calls (in particular, the inline call stack is not traversed
>> to accumulate samples).
>>
>> - Working sets and modules. These are used mostly for GCC's LIPO
>> optimizations, so they're not needed in LLVM atm. I'm not sure that
>> we will ever need them. For now, I've if0'd around the calls.
>>
>> The patch also adds support in GCOV.h for gcov version V704 (generated
>> by GCC's profile conversion tool).
>>
>> Added:
>> llvm/trunk/test/Transforms/SampleProfile/Inputs/gcc-simple.afdo
>> llvm/trunk/test/Transforms/SampleProfile/gcc-simple.ll
>> Modified:
>> llvm/trunk/include/llvm/ProfileData/SampleProf.h
>> llvm/trunk/include/llvm/ProfileData/SampleProfReader.h
>> llvm/trunk/include/llvm/Support/GCOV.h
>> llvm/trunk/lib/ProfileData/SampleProf.cpp
>> llvm/trunk/lib/ProfileData/SampleProfReader.cpp
>>
>> Modified: llvm/trunk/include/llvm/ProfileData/SampleProf.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/SampleProf.h?rev=247874&r1=247873&r2=247874&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/ProfileData/SampleProf.h (original)
>> +++ llvm/trunk/include/llvm/ProfileData/SampleProf.h Wed Sep 16 19:17:24
>> 2015
>> @@ -32,7 +32,8 @@ enum class sampleprof_error {
>> too_large,
>> truncated,
>> malformed,
>> - unrecognized_format
>> + unrecognized_format,
>> + not_implemented
>> };
>>
>> inline std::error_code make_error_code(sampleprof_error E) {
>>
>> Modified: llvm/trunk/include/llvm/ProfileData/SampleProfReader.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/SampleProfReader.h?rev=247874&r1=247873&r2=247874&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/ProfileData/SampleProfReader.h (original)
>> +++ llvm/trunk/include/llvm/ProfileData/SampleProfReader.h Wed Sep 16
>> 19:17:24 2015
>> @@ -24,6 +24,7 @@
>> #include "llvm/Support/Debug.h"
>> #include "llvm/Support/ErrorHandling.h"
>> #include "llvm/Support/ErrorOr.h"
>> +#include "llvm/Support/GCOV.h"
>> #include "llvm/Support/MemoryBuffer.h"
>> #include "llvm/Support/raw_ostream.h"
>>
>> @@ -57,7 +58,7 @@ namespace sampleprof {
>> ///
>> /// The reader supports two file formats: text and binary. The text
>> format
>> /// is useful for debugging and testing, while the binary format is more
>> -/// compact. They can both be used interchangeably.
>> +/// compact and I/O efficient. They can both be used interchangeably.
>> class SampleProfileReader {
>> public:
>> SampleProfileReader(std::unique_ptr<MemoryBuffer> B, LLVMContext &C)
>> @@ -86,7 +87,7 @@ public:
>> StringMap<FunctionSamples> &getProfiles() { return Profiles; }
>>
>> /// \brief Report a parse error message.
>> - void reportParseError(int64_t LineNumber, Twine Msg) const {
>> + void reportError(int64_t LineNumber, Twine Msg) const {
>>
>> Ctx.diagnose(DiagnosticInfoSampleProfile(Buffer->getBufferIdentifier(),
>> LineNumber, Msg));
>> }
>> @@ -163,6 +164,86 @@ protected:
>> const uint8_t *End;
>> };
>>
>> +// Represents the source position in GCC sample profiles.
>> +struct SourceInfo {
>> + SourceInfo()
>> + : FuncName(), DirName(), FileName(), StartLine(0), Line(0),
>> + Discriminator(0) {}
>> +
>> + SourceInfo(StringRef FuncName, StringRef DirName, StringRef FileName,
>> + uint32_t StartLine, uint32_t Line, uint32_t Discriminator)
>> + : FuncName(FuncName), DirName(DirName), FileName(FileName),
>> + StartLine(StartLine), Line(Line), Discriminator(Discriminator) {}
>> +
>> + bool operator<(const SourceInfo &p) const;
>> +
>> + uint32_t Offset() const { return ((Line - StartLine) << 16) |
>> Discriminator; }
>> +
>> + bool Malformed() const { return Line < StartLine; }
>> +
>> + StringRef FuncName;
>> + StringRef DirName;
>> + StringRef FileName;
>> + uint32_t StartLine;
>> + uint32_t Line;
>> + uint32_t Discriminator;
>> +};
>> +
>> +typedef std::vector<SourceInfo> SourceStack;
>> +
>> +// Supported histogram types in GCC. Currently, we only need support for
>> +// call target histograms.
>> +enum HistType {
>> + HIST_TYPE_INTERVAL,
>> + HIST_TYPE_POW2,
>> + HIST_TYPE_SINGLE_VALUE,
>> + HIST_TYPE_CONST_DELTA,
>> + HIST_TYPE_INDIR_CALL,
>> + HIST_TYPE_AVERAGE,
>> + HIST_TYPE_IOR,
>> + HIST_TYPE_INDIR_CALL_TOPN
>> +};
>> +
>> +class SampleProfileReaderGCC : public SampleProfileReader {
>> +public:
>> + SampleProfileReaderGCC(std::unique_ptr<MemoryBuffer> B, LLVMContext &C)
>> + : SampleProfileReader(std::move(B), C), GcovBuffer(Buffer.get()) {}
>> +
>> + /// \brief Read and validate the file header.
>> + std::error_code readHeader() override;
>> +
>> + /// \brief Read sample profiles from the associated file.
>> + std::error_code read() override;
>> +
>> + /// \brief Return true if \p Buffer is in the format supported by this
>> class.
>> + static bool hasFormat(const MemoryBuffer &Buffer);
>> +
>> +protected:
>> + std::error_code readNameTable();
>> + std::error_code addSourceCount(StringRef Name, const SourceStack &Src,
>> + uint64_t Count);
>> + std::error_code readOneFunctionProfile(const SourceStack &Stack, bool
>> Update);
>> + std::error_code readFunctionProfiles();
>> + std::error_code readModuleGroup();
>> + std::error_code readWorkingSet();
>> + std::error_code skipNextWord();
>> + template <typename T> ErrorOr<T> readNumber();
>> + ErrorOr<StringRef> readString();
>> +
>> + /// \brief Read the section tag and check that it's the same as \p
>> Expected.
>> + std::error_code readSectionTag(uint32_t Expected);
>> +
>> + /// GCOV buffer containing the profile.
>> + GCOVBuffer GcovBuffer;
>> +
>> + /// Function names in this profile.
>> + std::vector<std::string> Names;
>> +
>> + /// GCOV tags used to separate sections in the profile file.
>> + static const uint32_t GCOVTagAFDOFileNames = 0xaa000000;
>> + static const uint32_t GCOVTagAFDOFunction = 0xac000000;
>> +};
>> +
>> } // End namespace sampleprof
>>
>> } // End namespace llvm
>>
>> Modified: llvm/trunk/include/llvm/Support/GCOV.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/GCOV.h?rev=247874&r1=247873&r2=247874&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/Support/GCOV.h (original)
>> +++ llvm/trunk/include/llvm/Support/GCOV.h Wed Sep 16 19:17:24 2015
>> @@ -30,7 +30,7 @@ class GCOVBlock;
>> class FileInfo;
>>
>> namespace GCOV {
>> -enum GCOVVersion { V402, V404 };
>> +enum GCOVVersion { V402, V404, V704 };
>> } // end GCOV namespace
>>
>> /// GCOVOptions - A struct for passing gcov options between functions.
>> @@ -90,6 +90,11 @@ public:
>> Version = GCOV::V404;
>> return true;
>> }
>> + if (VersionStr == "*704") {
>> + Cursor += 4;
>> + Version = GCOV::V704;
>> + return true;
>> + }
>> errs() << "Unexpected version: " << VersionStr << ".\n";
>> return false;
>> }
>>
>> Modified: llvm/trunk/lib/ProfileData/SampleProf.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/SampleProf.cpp?rev=247874&r1=247873&r2=247874&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/ProfileData/SampleProf.cpp (original)
>> +++ llvm/trunk/lib/ProfileData/SampleProf.cpp Wed Sep 16 19:17:24 2015
>> @@ -38,6 +38,8 @@ class SampleProfErrorCategoryType : publ
>> return "Malformed profile data";
>> case sampleprof_error::unrecognized_format:
>> return "Unrecognized profile encoding format";
>> + case sampleprof_error::not_implemented:
>> + return "Unimplemented feature";
>> }
>> llvm_unreachable("A value of sampleprof_error has no message.");
>> }
>>
>> Modified: llvm/trunk/lib/ProfileData/SampleProfReader.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/SampleProfReader.cpp?rev=247874&r1=247873&r2=247874&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/ProfileData/SampleProfReader.cpp (original)
>> +++ llvm/trunk/lib/ProfileData/SampleProfReader.cpp Wed Sep 16 19:17:24
>> 2015
>> @@ -173,8 +173,8 @@ std::error_code SampleProfileReaderText:
>> // should not begin with a number.
>> SmallVector<StringRef, 4> Matches;
>> if (!HeadRE.match(*LineIt, &Matches)) {
>> - reportParseError(LineIt.line_number(),
>> - "Expected 'mangled_name:NUM:NUM', found " +
>> *LineIt);
>> + reportError(LineIt.line_number(),
>> + "Expected 'mangled_name:NUM:NUM', found " + *LineIt);
>> return sampleprof_error::malformed;
>> }
>> assert(Matches.size() == 4);
>> @@ -192,9 +192,9 @@ std::error_code SampleProfileReaderText:
>> // EOF or when we see the start of the next function.
>> while (!LineIt.is_at_eof() && isdigit((*LineIt)[0])) {
>> if (!LineSampleRE.match(*LineIt, &Matches)) {
>> - reportParseError(
>> - LineIt.line_number(),
>> - "Expected 'NUM[.NUM]: NUM[ mangled_name:NUM]*', found " +
>> *LineIt);
>> + reportError(LineIt.line_number(),
>> + "Expected 'NUM[.NUM]: NUM[ mangled_name:NUM]*', found
>> " +
>> + *LineIt);
>> return sampleprof_error::malformed;
>> }
>> assert(Matches.size() == 5);
>> @@ -210,8 +210,8 @@ std::error_code SampleProfileReaderText:
>> while (CallsLine != "") {
>> SmallVector<StringRef, 3> CallSample;
>> if (!CallSampleRE.match(CallsLine, &CallSample)) {
>> - reportParseError(LineIt.line_number(),
>> - "Expected 'mangled_name:NUM', found " +
>> CallsLine);
>> + reportError(LineIt.line_number(),
>> + "Expected 'mangled_name:NUM', found " + CallsLine);
>> return sampleprof_error::malformed;
>> }
>> StringRef CalledFunction = CallSample[1];
>> @@ -243,7 +243,7 @@ template <typename T> ErrorOr<T> SampleP
>> EC = sampleprof_error::success;
>>
>> if (EC) {
>> - reportParseError(0, EC.message());
>> + reportError(0, EC.message());
>> return EC;
>> }
>>
>> @@ -256,7 +256,7 @@ ErrorOr<StringRef> SampleProfileReaderBi
>> StringRef Str(reinterpret_cast<const char *>(Data));
>> if (Data + Str.size() + 1 > End) {
>> EC = sampleprof_error::truncated;
>> - reportParseError(0, EC.message());
>> + reportError(0, EC.message());
>> return EC;
>> }
>>
>> @@ -353,6 +353,264 @@ bool SampleProfileReaderBinary::hasForma
>> return Magic == SPMagic();
>> }
>>
>> +bool SourceInfo::operator<(const SourceInfo &P) const {
>> + if (Line != P.Line)
>> + return Line < P.Line;
>> + if (StartLine != P.StartLine)
>> + return StartLine < P.StartLine;
>> + if (Discriminator != P.Discriminator)
>> + return Discriminator < P.Discriminator;
>> + return FuncName < P.FuncName;
>> +}
>> +
>> +std::error_code SampleProfileReaderGCC::skipNextWord() {
>> + uint32_t dummy;
>> + if (!GcovBuffer.readInt(dummy))
>> + return sampleprof_error::truncated;
>> + return sampleprof_error::success;
>> +}
>> +
>> +template <typename T> ErrorOr<T> SampleProfileReaderGCC::readNumber() {
>> + if (sizeof(T) <= sizeof(uint32_t)) {
>> + uint32_t Val;
>> + if (GcovBuffer.readInt(Val) && Val <= std::numeric_limits<T>::max())
>> + return static_cast<T>(Val);
>> + } else if (sizeof(T) <= sizeof(uint64_t)) {
>> + uint64_t Val;
>> + if (GcovBuffer.readInt64(Val) && Val <=
>> std::numeric_limits<T>::max())
>> + return static_cast<T>(Val);
>> + }
>> +
>> + std::error_code EC = sampleprof_error::malformed;
>> + reportError(0, EC.message());
>> + return EC;
>> +}
>> +
>> +ErrorOr<StringRef> SampleProfileReaderGCC::readString() {
>> + StringRef Str;
>> + if (!GcovBuffer.readString(Str))
>> + return sampleprof_error::truncated;
>> + return Str;
>> +}
>> +
>> +std::error_code SampleProfileReaderGCC::readHeader() {
>> + // Read the magic identifier.
>> + if (!GcovBuffer.readGCDAFormat())
>> + return sampleprof_error::unrecognized_format;
>> +
>> + // Read the version number. Note - the GCC reader does not validate
>> this
>> + // version, but the profile creator generates v704.
>> + GCOV::GCOVVersion version;
>> + if (!GcovBuffer.readGCOVVersion(version))
>> + return sampleprof_error::unrecognized_format;
>> +
>> + if (version != GCOV::V704)
>> + return sampleprof_error::unsupported_version;
>> +
>> + // Skip the empty integer.
>> + if (std::error_code EC = skipNextWord())
>> + return EC;
>> +
>> + return sampleprof_error::success;
>> +}
>> +
>> +std::error_code SampleProfileReaderGCC::readSectionTag(uint32_t Expected)
>> {
>> + uint32_t Tag;
>> + if (!GcovBuffer.readInt(Tag))
>> + return sampleprof_error::truncated;
>> +
>> + if (Tag != Expected)
>> + return sampleprof_error::malformed;
>> +
>> + if (std::error_code EC = skipNextWord())
>> + return EC;
>> +
>> + return sampleprof_error::success;
>> +}
>> +
>> +std::error_code SampleProfileReaderGCC::readNameTable() {
>> + if (std::error_code EC = readSectionTag(GCOVTagAFDOFileNames))
>> + return EC;
>> +
>> + uint32_t Size;
>> + if (!GcovBuffer.readInt(Size))
>> + return sampleprof_error::truncated;
>> +
>> + for (uint32_t I = 0; I < Size; ++I) {
>> + StringRef Str;
>> + if (!GcovBuffer.readString(Str))
>> + return sampleprof_error::truncated;
>> + Names.push_back(Str);
>> + }
>> +
>> + return sampleprof_error::success;
>> +}
>> +
>> +std::error_code SampleProfileReaderGCC::readFunctionProfiles() {
>> + if (std::error_code EC = readSectionTag(GCOVTagAFDOFunction))
>> + return EC;
>> +
>> + uint32_t NumFunctions;
>> + if (!GcovBuffer.readInt(NumFunctions))
>> + return sampleprof_error::truncated;
>> +
>> + SourceStack Stack;
>> + for (uint32_t I = 0; I < NumFunctions; ++I)
>> + if (std::error_code EC = readOneFunctionProfile(Stack, true))
>> + return EC;
>> +
>> + return sampleprof_error::success;
>> +}
>> +
>> +std::error_code SampleProfileReaderGCC::addSourceCount(StringRef Name,
>> + const SourceStack
>> &Src,
>> + uint64_t Count) {
>> + if (Src.size() == 0 || Src[0].Malformed())
>> + return sampleprof_error::malformed;
>> + FunctionSamples &FProfile = Profiles[Name];
>> + FProfile.addTotalSamples(Count);
>> + // FIXME(dnovillo) - Properly update inline stack for FnName.
>> + FProfile.addBodySamples(Src[0].Line, Src[0].Discriminator, Count);
>> + return sampleprof_error::success;
>> +}
>> +
>> +
>> +std::error_code
>> +SampleProfileReaderGCC::readOneFunctionProfile(const SourceStack &Stack,
>> + bool Update) {
>> + uint64_t HeadCount = 0;
>> + if (Stack.size() == 0)
>> + if (!GcovBuffer.readInt64(HeadCount))
>> + return sampleprof_error::truncated;
>> +
>> + uint32_t NameIdx;
>> + if (!GcovBuffer.readInt(NameIdx))
>> + return sampleprof_error::truncated;
>> +
>> + StringRef Name(Names[NameIdx]);
>> +
>> + uint32_t NumPosCounts;
>> + if (!GcovBuffer.readInt(NumPosCounts))
>> + return sampleprof_error::truncated;
>> +
>> + uint32_t NumCallSites;
>> + if (!GcovBuffer.readInt(NumCallSites))
>> + return sampleprof_error::truncated;
>> +
>> + if (Stack.size() == 0) {
>> + FunctionSamples &FProfile = Profiles[Name];
>> + FProfile.addHeadSamples(HeadCount);
>> + if (FProfile.getTotalSamples() > 0)
>> + Update = false;
>> + }
>> +
>> + for (uint32_t I = 0; I < NumPosCounts; ++I) {
>> + uint32_t Offset;
>> + if (!GcovBuffer.readInt(Offset))
>> + return sampleprof_error::truncated;
>> +
>> + uint32_t NumTargets;
>> + if (!GcovBuffer.readInt(NumTargets))
>> + return sampleprof_error::truncated;
>> +
>> + uint64_t Count;
>> + if (!GcovBuffer.readInt64(Count))
>> + return sampleprof_error::truncated;
>> +
>> + SourceInfo Info(Name, "", "", 0, Offset >> 16, Offset & 0xffff);
>> + SourceStack NewStack;
>> + NewStack.push_back(Info);
>> + NewStack.insert(NewStack.end(), Stack.begin(), Stack.end());
>> + if (Update)
>> + addSourceCount(NewStack[NewStack.size() - 1].FuncName, NewStack,
>> Count);
>> +
>> + for (uint32_t J = 0; J < NumTargets; J++) {
>> + uint32_t HistVal;
>> + if (!GcovBuffer.readInt(HistVal))
>> + return sampleprof_error::truncated;
>> +
>> + if (HistVal != HIST_TYPE_INDIR_CALL_TOPN)
>> + return sampleprof_error::malformed;
>> +
>> + uint64_t TargetIdx;
>> + if (!GcovBuffer.readInt64(TargetIdx))
>> + return sampleprof_error::truncated;
>> + StringRef TargetName(Names[TargetIdx]);
>> +
>> + uint64_t TargetCount;
>> + if (!GcovBuffer.readInt64(TargetCount))
>> + return sampleprof_error::truncated;
>> +
>> + if (Update) {
>> + FunctionSamples &TargetProfile = Profiles[TargetName];
>> + TargetProfile.addBodySamples(NewStack[0].Line,
>> + NewStack[0].Discriminator,
>> TargetCount);
>> + }
>> + }
>> + }
>> +
>> + for (uint32_t I = 0; I < NumCallSites; I++) {
>> + // The offset is encoded as:
>> + // high 16 bits: line offset to the start of the function.
>> + // low 16 bits: discriminator.
>> + uint32_t Offset;
>> + if (!GcovBuffer.readInt(Offset))
>> + return sampleprof_error::truncated;
>> + SourceInfo Info(Name, "", "", 0, Offset >> 16, Offset & 0xffff);
>> + SourceStack NewStack;
>> + NewStack.push_back(Info);
>> + NewStack.insert(NewStack.end(), Stack.begin(), Stack.end());
>> + if (std::error_code EC = readOneFunctionProfile(NewStack, Update))
>> + return EC;
>> + }
>> +
>> + return sampleprof_error::success;
>> +}
>> +
>> +std::error_code SampleProfileReaderGCC::readModuleGroup() {
>> + // FIXME(dnovillo) - Module support still not implemented.
>> + return sampleprof_error::not_implemented;
>> +}
>> +
>> +std::error_code SampleProfileReaderGCC::readWorkingSet() {
>> + // FIXME(dnovillo) - Working sets still not implemented.
>> + return sampleprof_error::not_implemented;
>> +}
>> +
>> +
>> +/// \brief Read a GCC AutoFDO profile.
>> +///
>> +/// This format is generated by the Linux Perf conversion tool at
>> +/// https://github.com/google/autofdo.
>> +std::error_code SampleProfileReaderGCC::read() {
>> + // Read the string table.
>> + if (std::error_code EC = readNameTable())
>> + return EC;
>> +
>> + // Read the source profile.
>> + if (std::error_code EC = readFunctionProfiles())
>> + return EC;
>> +
>> + // FIXME(dnovillo) - Module groups and working set support are not
>> + // yet implemented.
>> +#if 0
>> + // Read the module group file.
>> + if (std::error_code EC = readModuleGroup())
>> + return EC;
>> +
>> + // Read the working set.
>> + if (std::error_code EC = readWorkingSet())
>> + return EC;
>> +#endif
>> +
>> + return sampleprof_error::success;
>> +}
>> +
>> +bool SampleProfileReaderGCC::hasFormat(const MemoryBuffer &Buffer) {
>> + StringRef Magic(reinterpret_cast<const char
>> *>(Buffer.getBufferStart()));
>> + return Magic == "adcg*704";
>> +}
>> +
>> /// \brief Prepare a memory buffer for the contents of \p Filename.
>> ///
>> /// \returns an error code indicating the status of the buffer.
>> @@ -389,6 +647,8 @@ SampleProfileReader::create(StringRef Fi
>> std::unique_ptr<SampleProfileReader> Reader;
>> if (SampleProfileReaderBinary::hasFormat(*Buffer))
>> Reader.reset(new SampleProfileReaderBinary(std::move(Buffer), C));
>> + else if (SampleProfileReaderGCC::hasFormat(*Buffer))
>> + Reader.reset(new SampleProfileReaderGCC(std::move(Buffer), C));
>> else
>> Reader.reset(new SampleProfileReaderText(std::move(Buffer), C));
>>
>>
>> Added: llvm/trunk/test/Transforms/SampleProfile/Inputs/gcc-simple.afdo
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SampleProfile/Inputs/gcc-simple.afdo?rev=247874&view=auto
>>
>> ==============================================================================
>> Binary files
>> llvm/trunk/test/Transforms/SampleProfile/Inputs/gcc-simple.afdo (added) and
>> llvm/trunk/test/Transforms/SampleProfile/Inputs/gcc-simple.afdo Wed Sep 16
>> 19:17:24 2015 differ
>>
>> Added: llvm/trunk/test/Transforms/SampleProfile/gcc-simple.ll
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SampleProfile/gcc-simple.ll?rev=247874&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/test/Transforms/SampleProfile/gcc-simple.ll (added)
>> +++ llvm/trunk/test/Transforms/SampleProfile/gcc-simple.ll Wed Sep 16
>> 19:17:24 2015
>> @@ -0,0 +1,218 @@
>> +; RUN: opt < %s -sample-profile
>> -sample-profile-file=%S/Inputs/gcc-simple.afdo -S | FileCheck %s
>> +;
>> +; Original code:
>> +;
>> +; #include <stdlib.h>
>> +;
>> +; long long int foo(long i) {
>> +; if (rand() < 500) return 2; else if (rand() > 5000) return 10; else
>> return 90;
>> +; }
>> +;
>> +; int main() {
>> +; long long int sum = 0;
>> +; for (int k = 0; k < 3000; k++)
>> +; for (int i = 0; i < 200000; i++) sum += foo(i);
>> +; return sum > 0 ? 0 : 1;
>> +; }
>> +;
>> +; This test was compiled down to bytecode at -O0 to avoid inlining foo()
>> into
>> +; main(). The profile was generated using a GCC-generated binary (also
>> compiled
>> +; at -O0). The conversion from the Linux Perf profile to the GCC autofdo
>> +; profile used the converter at https://github.com/google/autofdo
>> +;
>> +; $ gcc -g -O0 gcc-simple.cc -o gcc-simple
>> +; $ perf record -b ./gcc-simple
>> +; $ create_gcov --binary=gcc-simple --gcov=gcc-simple.afdo
>> +
>> +define i64 @_Z3fool(i64 %i) #0 {
>> +; CHECK: !prof ![[EC1:[0-9]+]]
>> +entry:
>> + %retval = alloca i64, align 8
>> + %i.addr = alloca i64, align 8
>> + store i64 %i, i64* %i.addr, align 8
>> + call void @llvm.dbg.declare(metadata i64* %i.addr, metadata !16,
>> metadata !17), !dbg !18
>> + %call = call i32 @rand() #3, !dbg !19
>> + %cmp = icmp slt i32 %call, 500, !dbg !21
>> + br i1 %cmp, label %if.then, label %if.else, !dbg !22
>> +; CHECK: !prof ![[PROF1:[0-9]+]]
>> +
>> +if.then: ; preds = %entry
>> + store i64 2, i64* %retval, align 8, !dbg !23
>> + br label %return, !dbg !23
>> +
>> +if.else: ; preds = %entry
>> + %call1 = call i32 @rand() #3, !dbg !25
>> + %cmp2 = icmp sgt i32 %call1, 5000, !dbg !28
>> + br i1 %cmp2, label %if.then.3, label %if.else.4, !dbg !29
>> +; CHECK: !prof ![[PROF2:[0-9]+]]
>> +
>> +if.then.3: ; preds = %if.else
>> + store i64 10, i64* %retval, align 8, !dbg !30
>> + br label %return, !dbg !30
>> +
>> +if.else.4: ; preds = %if.else
>> + store i64 90, i64* %retval, align 8, !dbg !32
>> + br label %return, !dbg !32
>> +
>> +return: ; preds = %if.else.4,
>> %if.then.3, %if.then
>> + %0 = load i64, i64* %retval, align 8, !dbg !34
>> + ret i64 %0, !dbg !34
>> +}
>> +
>> +; Function Attrs: nounwind readnone
>> +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
>> +
>> +; Function Attrs: nounwind
>> +declare i32 @rand() #2
>> +
>> +; Function Attrs: nounwind uwtable
>> +define i32 @main() #0 {
>> +; CHECK: !prof ![[EC2:[0-9]+]]
>> +entry:
>> + %retval = alloca i32, align 4
>> + %sum = alloca i64, align 8
>> + %k = alloca i32, align 4
>> + %i = alloca i32, align 4
>> + store i32 0, i32* %retval, align 4
>> + call void @llvm.dbg.declare(metadata i64* %sum, metadata !35, metadata
>> !17), !dbg !36
>> + store i64 0, i64* %sum, align 8, !dbg !36
>> + call void @llvm.dbg.declare(metadata i32* %k, metadata !37, metadata
>> !17), !dbg !39
>> + store i32 0, i32* %k, align 4, !dbg !39
>> + br label %for.cond, !dbg !40
>> +
>> +for.cond: ; preds = %for.inc.4,
>> %entry
>> + %0 = load i32, i32* %k, align 4, !dbg !41
>> + %cmp = icmp slt i32 %0, 3000, !dbg !45
>> + br i1 %cmp, label %for.body, label %for.end.6, !dbg !46
>> +; CHECK: !prof ![[PROF3:[0-9]+]]
>> +
>> +for.body: ; preds = %for.cond
>> + call void @llvm.dbg.declare(metadata i32* %i, metadata !47, metadata
>> !17), !dbg !49
>> + store i32 0, i32* %i, align 4, !dbg !49
>> + br label %for.cond.1, !dbg !50
>> +
>> +for.cond.1: ; preds = %for.inc,
>> %for.body
>> + %1 = load i32, i32* %i, align 4, !dbg !51
>> + %cmp2 = icmp slt i32 %1, 200000, !dbg !55
>> + br i1 %cmp2, label %for.body.3, label %for.end, !dbg !56
>> +; CHECK: !prof ![[PROF4:[0-9]+]]
>> +
>> +for.body.3: ; preds = %for.cond.1
>> + %2 = load i32, i32* %i, align 4, !dbg !57
>> + %conv = sext i32 %2 to i64, !dbg !57
>> + %call = call i64 @_Z3fool(i64 %conv), !dbg !59
>> + %3 = load i64, i64* %sum, align 8, !dbg !60
>> + %add = add nsw i64 %3, %call, !dbg !60
>> + store i64 %add, i64* %sum, align 8, !dbg !60
>> + br label %for.inc, !dbg !61
>> +
>> +for.inc: ; preds = %for.body.3
>> + %4 = load i32, i32* %i, align 4, !dbg !62
>> + %inc = add nsw i32 %4, 1, !dbg !62
>> + store i32 %inc, i32* %i, align 4, !dbg !62
>> + br label %for.cond.1, !dbg !64
>> +
>> +for.end: ; preds = %for.cond.1
>> + br label %for.inc.4, !dbg !65
>> +
>> +for.inc.4: ; preds = %for.end
>> + %5 = load i32, i32* %k, align 4, !dbg !67
>> + %inc5 = add nsw i32 %5, 1, !dbg !67
>> + store i32 %inc5, i32* %k, align 4, !dbg !67
>> + br label %for.cond, !dbg !68
>> +
>> +for.end.6: ; preds = %for.cond
>> + %6 = load i64, i64* %sum, align 8, !dbg !69
>> + %cmp7 = icmp sgt i64 %6, 0, !dbg !70
>> + %cond = select i1 %cmp7, i32 0, i32 1, !dbg !69
>> + ret i32 %cond, !dbg !71
>> +}
>> +
>> +; CHECK ![[EC1]] = !{!"function_entry_count", i64 24108}
>> +; CHECK ![[PROF1]] = !{!"branch_weights", i32 1, i32 30124}
>> +; CHECK ![[PROF2]] = !{!"branch_weights", i32 30177, i32 29579}
>> +; CHECK ![[EC2]] = !{!"function_entry_count", i64 0}
>> +; CHECK ![[PROF3]] = !{!"branch_weights", i32 1, i32 1}
>> +; CHECK ![[PROF4]] = !{!"branch_weights", i32 1, i32 20238}
>> +
>> +attributes #0 = { nounwind uwtable "disable-tail-calls"="false"
>> "less-precise-fpmad"="false" "no-frame-pointer-elim"="true"
>> "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false"
>> "no-nans-fp-math"="false" "stack-protector-buffer-size"="8"
>> "target-cpu"="x86-64" "target-features"="+sse,+sse2"
>> "unsafe-fp-math"="false" "use-soft-float"="false" }
>> +attributes #1 = { nounwind readnone }
>> +attributes #2 = { nounwind "disable-tail-calls"="false"
>> "less-precise-fpmad"="false" "no-frame-pointer-elim"="true"
>> "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false"
>> "no-nans-fp-math"="false" "stack-protector-buffer-size"="8"
>> "target-cpu"="x86-64" "target-features"="+sse,+sse2"
>> "unsafe-fp-math"="false" "use-soft-float"="false" }
>> +attributes #3 = { nounwind }
>> +
>> +!llvm.dbg.cu = !{!0}
>> +!llvm.module.flags = !{!13, !14}
>> +!llvm.ident = !{!15}
>> +
>> +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1,
>> producer: "clang version 3.8.0 (trunk 247554) (llvm/trunk 247557)",
>> isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2,
>> subprograms: !3)
>> +!1 = !DIFile(filename: "discriminator.cc", directory:
>> "/usr/local/google/home/dnovillo/llvm/test/autofdo")
>> +!2 = !{}
>> +!3 = !{!4, !9}
>> +!4 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fool", scope:
>> !1, file: !1, line: 3, type: !5, isLocal: false, isDefinition: true,
>> scopeLine: 3, flags: DIFlagPrototyped, isOptimized: false, function: i64
>> (i64)* @_Z3fool, variables: !2)
>> +!5 = !DISubroutineType(types: !6)
>> +!6 = !{!7, !8}
>> +!7 = !DIBasicType(name: "long long int", size: 64, align: 64, encoding:
>> DW_ATE_signed)
>> +!8 = !DIBasicType(name: "long int", size: 64, align: 64, encoding:
>> DW_ATE_signed)
>> +!9 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 7,
>> type: !10, isLocal: false, isDefinition: true, scopeLine: 7, flags:
>> DIFlagPrototyped, isOptimized: false, function: i32 ()* @main, variables:
>> !2)
>> +!10 = !DISubroutineType(types: !11)
>> +!11 = !{!12}
>> +!12 = !DIBasicType(name: "int", size: 32, align: 32, encoding:
>> DW_ATE_signed)
>> +!13 = !{i32 2, !"Dwarf Version", i32 4}
>> +!14 = !{i32 2, !"Debug Info Version", i32 3}
>> +!15 = !{!"clang version 3.8.0 (trunk 247554) (llvm/trunk 247557)"}
>> +!16 = !DILocalVariable(name: "i", arg: 1, scope: !4, file: !1, line: 3,
>> type: !8)
>> +!17 = !DIExpression()
>> +!18 = !DILocation(line: 3, column: 24, scope: !4)
>> +!19 = !DILocation(line: 4, column: 7, scope: !20)
>> +!20 = distinct !DILexicalBlock(scope: !4, file: !1, line: 4, column: 7)
>> +!21 = !DILocation(line: 4, column: 14, scope: !20)
>> +!22 = !DILocation(line: 4, column: 7, scope: !4)
>> +!23 = !DILocation(line: 4, column: 21, scope: !24)
>> +!24 = !DILexicalBlockFile(scope: !20, file: !1, discriminator: 1)
>> +!25 = !DILocation(line: 4, column: 40, scope: !26)
>> +!26 = !DILexicalBlockFile(scope: !27, file: !1, discriminator: 2)
>> +!27 = distinct !DILexicalBlock(scope: !20, file: !1, line: 4, column: 40)
>> +!28 = !DILocation(line: 4, column: 47, scope: !27)
>> +!29 = !DILocation(line: 4, column: 40, scope: !20)
>> +!30 = !DILocation(line: 4, column: 55, scope: !31)
>> +!31 = !DILexicalBlockFile(scope: !27, file: !1, discriminator: 3)
>> +!32 = !DILocation(line: 4, column: 71, scope: !33)
>> +!33 = !DILexicalBlockFile(scope: !27, file: !1, discriminator: 4)
>> +!34 = !DILocation(line: 5, column: 1, scope: !4)
>> +!35 = !DILocalVariable(name: "sum", scope: !9, file: !1, line: 8, type:
>> !7)
>> +!36 = !DILocation(line: 8, column: 17, scope: !9)
>> +!37 = !DILocalVariable(name: "k", scope: !38, file: !1, line: 9, type:
>> !12)
>> +!38 = distinct !DILexicalBlock(scope: !9, file: !1, line: 9, column: 3)
>> +!39 = !DILocation(line: 9, column: 12, scope: !38)
>> +!40 = !DILocation(line: 9, column: 8, scope: !38)
>> +!41 = !DILocation(line: 9, column: 19, scope: !42)
>> +!42 = !DILexicalBlockFile(scope: !43, file: !1, discriminator: 2)
>> +!43 = !DILexicalBlockFile(scope: !44, file: !1, discriminator: 1)
>> +!44 = distinct !DILexicalBlock(scope: !38, file: !1, line: 9, column: 3)
>> +!45 = !DILocation(line: 9, column: 21, scope: !44)
>> +!46 = !DILocation(line: 9, column: 3, scope: !38)
>> +!47 = !DILocalVariable(name: "i", scope: !48, file: !1, line: 10, type:
>> !12)
>> +!48 = distinct !DILexicalBlock(scope: !44, file: !1, line: 10, column: 5)
>> +!49 = !DILocation(line: 10, column: 14, scope: !48)
>> +!50 = !DILocation(line: 10, column: 10, scope: !48)
>> +!51 = !DILocation(line: 10, column: 21, scope: !52)
>> +!52 = !DILexicalBlockFile(scope: !53, file: !1, discriminator: 5)
>> +!53 = !DILexicalBlockFile(scope: !54, file: !1, discriminator: 1)
>> +!54 = distinct !DILexicalBlock(scope: !48, file: !1, line: 10, column: 5)
>> +!55 = !DILocation(line: 10, column: 23, scope: !54)
>> +!56 = !DILocation(line: 10, column: 5, scope: !48)
>> +!57 = !DILocation(line: 10, column: 49, scope: !58)
>> +!58 = !DILexicalBlockFile(scope: !54, file: !1, discriminator: 2)
>> +!59 = !DILocation(line: 10, column: 45, scope: !54)
>> +!60 = !DILocation(line: 10, column: 42, scope: !54)
>> +!61 = !DILocation(line: 10, column: 38, scope: !54)
>> +!62 = !DILocation(line: 10, column: 34, scope: !63)
>> +!63 = !DILexicalBlockFile(scope: !54, file: !1, discriminator: 4)
>> +!64 = !DILocation(line: 10, column: 5, scope: !54)
>> +!65 = !DILocation(line: 10, column: 50, scope: !66)
>> +!66 = !DILexicalBlockFile(scope: !48, file: !1, discriminator: 3)
>> +!67 = !DILocation(line: 9, column: 30, scope: !44)
>> +!68 = !DILocation(line: 9, column: 3, scope: !44)
>> +!69 = !DILocation(line: 11, column: 10, scope: !9)
>> +!70 = !DILocation(line: 11, column: 14, scope: !9)
>> +!71 = !DILocation(line: 11, column: 3, scope: !9)
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
>
More information about the llvm-commits
mailing list