Index: ProfileData/InstrProfData.inc =================================================================== --- ProfileData/InstrProfData.inc +++ ProfileData/InstrProfData.inc @@ -700,9 +700,11 @@ * version for other variants of profile. We set the lowest bit of the upper 8 * bits (i.e. bit 56) to 1 to indicate if this is an IR-level instrumentaiton * generated profile, and 0 if this is a Clang FE generated profile. -*/ + */ #define VARIANT_MASKS_ALL 0xff00000000000000ULL #define GET_VERSION(V) ((V) & ~VARIANT_MASKS_ALL) +#define VARIANT_MASK_IR_PROF (0x1ULL << 56) +#define IR_LEVEL_PROF_VERSION_VAR __llvm_profile_raw_version /* Runtime section names and name strings. */ #define INSTR_PROF_DATA_SECT_NAME __llvm_prf_data Index: ProfileData/InstrProfReader.h =================================================================== --- ProfileData/InstrProfReader.h +++ ProfileData/InstrProfReader.h @@ -64,6 +64,7 @@ /// Iterator over profile data. InstrProfIterator begin() { return InstrProfIterator(this); } InstrProfIterator end() { return InstrProfIterator(); } + virtual bool isIRLevelProfile() const = 0; /// Return the PGO symtab. There are three different readers: /// Raw, Text, and Indexed profile readers. The first two types @@ -118,6 +119,7 @@ std::unique_ptr DataBuffer; /// Iterator over the profile data. line_iterator Line; + bool IsIRLevelProfile; TextInstrProfReader(const TextInstrProfReader &) = delete; TextInstrProfReader &operator=(const TextInstrProfReader &) = delete; @@ -125,11 +127,14 @@ public: TextInstrProfReader(std::unique_ptr DataBuffer_) - : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {} + : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#'), + IsIRLevelProfile(false) {} /// Return true if the given buffer is in text instrprof format. static bool hasFormat(const MemoryBuffer &Buffer); + bool isIRLevelProfile() const override { return IsIRLevelProfile; } + /// Read the header. std::error_code readHeader() override; /// Read a single record. @@ -154,6 +159,10 @@ /// The profile data file contents. std::unique_ptr DataBuffer; bool ShouldSwapBytes; + // The value of the version field of the raw profile data header. The lower 56 + // bits specifies the format version and the most significant 8 bits specify + // the variant types of the profile. + uint64_t Version; uint64_t CountersDelta; uint64_t NamesDelta; const RawInstrProf::ProfileData *Data; @@ -176,6 +185,9 @@ static bool hasFormat(const MemoryBuffer &DataBuffer); std::error_code readHeader() override; std::error_code readNextRecord(InstrProfRecord &Record) override; + bool isIRLevelProfile() const override { + return (Version & VARIANT_MASK_IR_PROF) != 0; + } InstrProfSymtab &getSymtab() override { assert(Symtab.get()); @@ -292,6 +304,7 @@ virtual void setValueProfDataEndianness(support::endianness Endianness) = 0; virtual ~InstrProfReaderIndexBase() {} virtual uint64_t getVersion() const = 0; + virtual bool isIRLevelProfile() const = 0; virtual void populateSymtab(InstrProfSymtab &) = 0; }; @@ -323,7 +336,10 @@ HashTable->getInfoObj().setValueProfDataEndianness(Endianness); } ~InstrProfReaderIndex() override {} - uint64_t getVersion() const override { return FormatVersion; } + uint64_t getVersion() const override { return GET_VERSION(FormatVersion); } + bool isIRLevelProfile() const override { + return (FormatVersion & VARIANT_MASK_IR_PROF) != 0; + } void populateSymtab(InstrProfSymtab &Symtab) override { Symtab.create(HashTable->keys()); } @@ -348,7 +364,9 @@ const unsigned char *Cur); public: + /// Return the profile version. uint64_t getVersion() const { return Index->getVersion(); } + bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); } IndexedInstrProfReader(std::unique_ptr DataBuffer) : DataBuffer(std::move(DataBuffer)), Index(nullptr) {} Index: ProfileData/InstrProfWriter.h =================================================================== --- ProfileData/InstrProfWriter.h +++ ProfileData/InstrProfWriter.h @@ -30,10 +30,12 @@ class InstrProfWriter { public: typedef SmallDenseMap ProfilingData; + enum ProfKind { PF_Unknown = 0, PF_FE, PF_IRLevel }; private: bool Sparse; StringMap FunctionData; + ProfKind ProfileKind; // Use raw pointer here for the incomplete type object. InstrProfRecordWriterTrait *InfoObj; @@ -55,6 +57,16 @@ /// Write the profile, returning the raw data. For testing. std::unique_ptr writeBuffer(); + /// Set the ProfileKind. Report error if mixing FE and IR level profiles. + std::error_code setIsIRLevelProfile(bool IsIRLevel) { + if (ProfileKind == PF_Unknown) { + ProfileKind = IsIRLevel ? PF_IRLevel: PF_FE; + return instrprof_error::success; + } + return (IsIRLevel == (ProfileKind == PF_IRLevel)) ? + instrprof_error::success : instrprof_error::unsupported_version; + } + // Internal interface for testing purpose only. void setValueProfDataEndianness(support::endianness Endianness); void setOutputSparse(bool Sparse);