From 72f9544cc033e9e7316691f0f210672c9639cb14 Mon Sep 17 00:00:00 2001 From: Xinliang David Li Date: Wed, 25 Nov 2015 06:23:38 +0000 Subject: [PATCH 1/1] [PGO] Convert InstrProfRecord based serialization methods to use common C methods 1. Convert serialization methods using InstrProfRecord as source into C (impl) interfaces using Closure. 2. Reimplement InstrProfRecord serialization method to use new C interface as dummy wrapper. Now it is ready to implement wrapper for runtime value profile data. (The new code need better source location -- but not changed in this patch to minimize diffs. ) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254057 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ProfileData/InstrProf.h | 25 +++-- lib/ProfileData/InstrProf.cpp | 132 ++++++++++++++++++++------- 2 files changed, 109 insertions(+), 48 deletions(-) diff --git a/include/llvm/ProfileData/InstrProf.h b/include/llvm/ProfileData/InstrProf.h index c03f6cc4616..3c1a4d08277 100644 --- a/include/llvm/ProfileData/InstrProf.h +++ b/include/llvm/ProfileData/InstrProf.h @@ -474,9 +474,6 @@ typedef struct ValueProfRecord { /// Read data from this record and save it to Record. void deserializeTo(InstrProfRecord &Record, InstrProfRecord::ValueMapType *VMap); - /// Extract data from \c Record and serialize into this instance. - void serializeFrom(const InstrProfRecord &Record, uint32_t ValueKind, - uint32_t NumValueSites); /// In-place byte swap: /// Do byte swap for this instance. \c Old is the original order before /// the swap, and \c New is the New byte order. @@ -524,8 +521,6 @@ typedef struct ValueProfData { /// Read data from this data and save it to \c Record. void deserializeTo(InstrProfRecord &Record, InstrProfRecord::ValueMapType *VMap); - /// Return the first \c ValueProfRecord instance. - ValueProfRecord *getFirstValueProfRecord(); } ValueProfData; /* The closure is designed to abstact away two types of value profile data: @@ -542,21 +537,20 @@ typedef struct ValueProfData { * in class InstrProfRecord. */ typedef struct ValueProfRecordClosure { - void *Record; - uint32_t (*GetNumValueKinds)(void *Record); - uint32_t (*GetNumValueSites)(void *Record, uint32_t VKind); - uint32_t (*GetNumValueData)(void *Record, uint32_t VKind); - uint32_t (*GetNumValueDataForSite)(void *R, uint32_t VK, uint32_t S); + const void *Record; + uint32_t (*GetNumValueKinds)(const void *Record); + uint32_t (*GetNumValueSites)(const void *Record, uint32_t VKind); + uint32_t (*GetNumValueData)(const void *Record, uint32_t VKind); + uint32_t (*GetNumValueDataForSite)(const void *R, uint32_t VK, uint32_t S); /* After extracting the value profile data from the value profile record, * this method is used to map the in-memory value to on-disk value. If * the method is null, value will be written out untranslated. */ uint64_t (*RemapValueData)(uint32_t, uint64_t Value); - void (*GetValueForSite)(InstrProfValueData *Dst, void *R, uint32_t K, + void (*GetValueForSite)(const void *R, InstrProfValueData *Dst, uint32_t K, uint32_t S, uint64_t (*Mapper)(uint32_t, uint64_t)); - - ValueProfData *(*AllocateValueProfData)(size_t TotalSizeInBytes); + ValueProfData *(*AllocValueProfData)(size_t TotalSizeInBytes); } ValueProfRecordClosure; /// Return the \c ValueProfRecord header size including the padding bytes. @@ -599,6 +593,11 @@ inline ValueProfRecord *getValueProfRecordNext(ValueProfRecord *This) { NumValueData)); } +/// Return the first \c ValueProfRecord instance. +inline ValueProfRecord *getFirstValueProfRecord(ValueProfData *This) { + return (ValueProfRecord *)((char *)This + sizeof(ValueProfData)); +} + namespace IndexedInstrProf { enum class HashT : uint32_t { diff --git a/lib/ProfileData/InstrProf.cpp b/lib/ProfileData/InstrProf.cpp index 34a354da896..87757af7f19 100644 --- a/lib/ProfileData/InstrProf.cpp +++ b/lib/ProfileData/InstrProf.cpp @@ -155,16 +155,21 @@ void ValueProfRecord::deserializeTo(InstrProfRecord &Record, } } -void ValueProfRecord::serializeFrom(const InstrProfRecord &Record, - uint32_t ValueKind, - uint32_t NumValueSites) { - Kind = ValueKind; - this->NumValueSites = NumValueSites; - InstrProfValueData *DstVD = getValueProfRecordValueData(this); - for (uint32_t S = 0; S < NumValueSites; S++) { - uint32_t ND = Record.getNumValueDataForSite(ValueKind, S); - SiteCountArray[S] = ND; - Record.getValueForSite(DstVD, ValueKind, S, stringToHash); +// Extract data from \c Closure and serialize into \c This instance. +void serializeValueProfRecordFrom(ValueProfRecord *This, + ValueProfRecordClosure *Closure, + uint32_t ValueKind, uint32_t NumValueSites) { + uint32_t S; + const void *Record = Closure->Record; + This->Kind = ValueKind; + This->NumValueSites = NumValueSites; + InstrProfValueData *DstVD = getValueProfRecordValueData(This); + + for (S = 0; S < NumValueSites; S++) { + uint32_t ND = Closure->GetNumValueDataForSite(Record, ValueKind, S); + This->SiteCountArray[S] = ND; + Closure->GetValueForSite(Record, DstVD, ValueKind, S, + Closure->RemapValueData); DstVD += ND; } } @@ -205,18 +210,22 @@ void ValueProfRecord::swapBytes(support::endianness Old, } } -uint32_t ValueProfData::getSize(const InstrProfRecord &Record) { +/// Return the total size in bytes of the on-disk value profile data +/// given the data stored in Record. +uint32_t getValueProfDataSize(ValueProfRecordClosure *Closure) { + uint32_t Kind; uint32_t TotalSize = sizeof(ValueProfData); - uint32_t NumValueKinds = Record.getNumValueKinds(); + const void *Record = Closure->Record; + uint32_t NumValueKinds = Closure->GetNumValueKinds(Record); if (NumValueKinds == 0) return TotalSize; - for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; Kind++) { - uint32_t NumValueSites = Record.getNumValueSites(Kind); + for (Kind = IPVK_First; Kind <= IPVK_Last; Kind++) { + uint32_t NumValueSites = Closure->GetNumValueSites(Record, Kind); if (!NumValueSites) continue; - TotalSize += - getValueProfRecordSize(NumValueSites, Record.getNumValueData(Kind)); + TotalSize += getValueProfRecordSize(NumValueSites, + Closure->GetNumValueData(Record, Kind)); } return TotalSize; } @@ -226,37 +235,95 @@ void ValueProfData::deserializeTo(InstrProfRecord &Record, if (NumValueKinds == 0) return; - ValueProfRecord *VR = getFirstValueProfRecord(); + ValueProfRecord *VR = getFirstValueProfRecord(this); for (uint32_t K = 0; K < NumValueKinds; K++) { VR->deserializeTo(Record, VMap); VR = getValueProfRecordNext(VR); } } -static std::unique_ptr AllocValueProfData(uint32_t TotalSize) { +static std::unique_ptr allocValueProfData(uint32_t TotalSize) { return std::unique_ptr(new (::operator new(TotalSize)) ValueProfData()); } -std::unique_ptr -ValueProfData::serializeFrom(const InstrProfRecord &Record) { - uint32_t TotalSize = getSize(Record); +ValueProfData *serializeValueProfDataFrom(ValueProfRecordClosure *Closure) { + uint32_t TotalSize = getValueProfDataSize(Closure); - std::unique_ptr VPD = AllocValueProfData(TotalSize); + ValueProfData *VPD = Closure->AllocValueProfData(TotalSize); VPD->TotalSize = TotalSize; - VPD->NumValueKinds = Record.getNumValueKinds(); - ValueProfRecord *VR = VPD->getFirstValueProfRecord(); + VPD->NumValueKinds = Closure->GetNumValueKinds(Closure->Record); + ValueProfRecord *VR = getFirstValueProfRecord(VPD); for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; Kind++) { - uint32_t NumValueSites = Record.getNumValueSites(Kind); + uint32_t NumValueSites = Closure->GetNumValueSites(Closure->Record, Kind); if (!NumValueSites) continue; - VR->serializeFrom(Record, Kind, NumValueSites); + serializeValueProfRecordFrom(VR, Closure, Kind, NumValueSites); VR = getValueProfRecordNext(VR); } return VPD; } +// C wrappers of InstrProfRecord member functions used in Closure. +// These C wrappers are used as adaptors so that C++ code can be +// invoked as callbacks. +uint32_t getNumValueKindsInstrProf(const void *Record) { + return reinterpret_cast(Record)->getNumValueKinds(); +} + +uint32_t getNumValueSitesInstrProf(const void *Record, uint32_t VKind) { + return reinterpret_cast(Record) + ->getNumValueSites(VKind); +} + +uint32_t getNumValueDataInstrProf(const void *Record, uint32_t VKind) { + return reinterpret_cast(Record) + ->getNumValueData(VKind); +} + +uint32_t getNumValueDataForSiteInstrProf(const void *R, uint32_t VK, + uint32_t S) { + return reinterpret_cast(R) + ->getNumValueDataForSite(VK, S); +} + +void getValueForSiteInstrProf(const void *R, InstrProfValueData *Dst, + uint32_t K, uint32_t S, + uint64_t (*Mapper)(uint32_t, uint64_t)) { + return reinterpret_cast(R) + ->getValueForSite(Dst, K, S, Mapper); +} + +ValueProfData *allocValueProfDataInstrProf(size_t TotalSizeInBytes) { + return (ValueProfData *)(new (::operator new(TotalSizeInBytes)) + ValueProfData()); +} + +static ValueProfRecordClosure InstrProfRecordClosure = { + 0, + getNumValueKindsInstrProf, + getNumValueSitesInstrProf, + getNumValueDataInstrProf, + getNumValueDataForSiteInstrProf, + stringToHash, + getValueForSiteInstrProf, + allocValueProfDataInstrProf}; + +uint32_t ValueProfData::getSize(const InstrProfRecord &Record) { + InstrProfRecordClosure.Record = &Record; + return getValueProfDataSize(&InstrProfRecordClosure); +} + +std::unique_ptr +ValueProfData::serializeFrom(const InstrProfRecord &Record) { + InstrProfRecordClosure.Record = &Record; + + std::unique_ptr VPD( + serializeValueProfDataFrom(&InstrProfRecordClosure)); + return VPD; +} + ErrorOr> ValueProfData::getValueProfData(const unsigned char *D, const unsigned char *const BufferEnd, @@ -277,14 +344,14 @@ ValueProfData::getValueProfData(const unsigned char *D, if (TotalSize % sizeof(uint64_t)) return instrprof_error::malformed; - std::unique_ptr VPD = AllocValueProfData(TotalSize); + std::unique_ptr VPD = allocValueProfData(TotalSize); memcpy(VPD.get(), D, TotalSize); // Byte swap. VPD->swapBytesToHost(Endianness); // Data integrity check: - ValueProfRecord *VR = VPD->getFirstValueProfRecord(); + ValueProfRecord *VR = getFirstValueProfRecord(VPD.get()); for (uint32_t K = 0; K < VPD->NumValueKinds; K++) { if (VR->Kind > IPVK_Last) return instrprof_error::malformed; @@ -304,7 +371,7 @@ void ValueProfData::swapBytesToHost(support::endianness Endianness) { sys::swapByteOrder(TotalSize); sys::swapByteOrder(NumValueKinds); - ValueProfRecord *VR = getFirstValueProfRecord(); + ValueProfRecord *VR = getFirstValueProfRecord(this); for (uint32_t K = 0; K < NumValueKinds; K++) { VR->swapBytes(Endianness, getHostEndianness()); VR = getValueProfRecordNext(VR); @@ -316,7 +383,7 @@ void ValueProfData::swapBytesFromHost(support::endianness Endianness) { if (Endianness == getHostEndianness()) return; - ValueProfRecord *VR = getFirstValueProfRecord(); + ValueProfRecord *VR = getFirstValueProfRecord(this); for (uint32_t K = 0; K < NumValueKinds; K++) { ValueProfRecord *NVR = getValueProfRecordNext(VR); VR->swapBytes(getHostEndianness(), Endianness); @@ -325,9 +392,4 @@ void ValueProfData::swapBytesFromHost(support::endianness Endianness) { sys::swapByteOrder(TotalSize); sys::swapByteOrder(NumValueKinds); } - -ValueProfRecord *ValueProfData::getFirstValueProfRecord() { - return reinterpret_cast((char *)this + - sizeof(ValueProfData)); -} } -- 2.34.1