[llvm] r247874 - GCC AutoFDO profile reader - Initial support.
Diego Novillo via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 16 17:40:04 PDT 2015
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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150916/480de953/attachment-0001.html>
More information about the llvm-commits
mailing list