Index: include/llvm/ProfileData/InstrProf.h =================================================================== --- include/llvm/ProfileData/InstrProf.h +++ include/llvm/ProfileData/InstrProf.h @@ -487,7 +487,8 @@ AddrToMD5Map.push_back(std::make_pair(Addr, MD5Val)); } - AddrHashMap &getAddrHashMap() { return AddrToMD5Map; } + /// Return a function's hash, or 0, if the function isn't in this SymTab. + uint64_t getFunctionHashFromAddress(uint64_t Address); /// Return function's PGO name from the function name's symbol /// address in the object file. If an error occurs, return @@ -643,8 +644,6 @@ return *this; } - using ValueMapType = std::vector>; - /// Return the number of value profile kinds with non-zero number /// of profile sites. inline uint32_t getNumValueKinds() const; @@ -678,7 +677,7 @@ /// Add ValueData for ValueKind at value Site. void addValueData(uint32_t ValueKind, uint32_t Site, InstrProfValueData *VData, uint32_t N, - ValueMapType *ValueMap); + InstrProfSymtab *SymTab); /// Merge the counts in \p Other into this one. /// Optionally scale merged counts by \p Weight. @@ -752,7 +751,7 @@ // Map indirect call target name hash to name string. uint64_t remapValue(uint64_t Value, uint32_t ValueKind, - ValueMapType *HashKeys); + InstrProfSymtab *SymTab); // Merge Value Profile data from Src record to this record for ValueKind. // Scale merged value counts by \p Weight. Index: include/llvm/ProfileData/InstrProfData.inc =================================================================== --- include/llvm/ProfileData/InstrProfData.inc +++ include/llvm/ProfileData/InstrProfData.inc @@ -315,7 +315,7 @@ * \brief Read data from this record and save it to Record. */ void deserializeTo(InstrProfRecord &Record, - InstrProfRecord::ValueMapType *VMap); + InstrProfSymtab *SymTab); /* * In-place byte swap: * Do byte swap for this instance. \c Old is the original order before @@ -393,7 +393,7 @@ * Read data from this data and save it to \c Record. */ void deserializeTo(InstrProfRecord &Record, - InstrProfRecord::ValueMapType *VMap); + InstrProfSymtab *SymTab); void operator delete(void *ptr) { ::operator delete(ptr); } #endif } ValueProfData; Index: include/llvm/ProfileData/InstrProfReader.h =================================================================== --- include/llvm/ProfileData/InstrProfReader.h +++ include/llvm/ProfileData/InstrProfReader.h @@ -199,8 +199,6 @@ uint32_t ValueKindLast; uint32_t CurValueDataSize; - InstrProfRecord::ValueMapType FunctionPtrToNameMap; - public: RawInstrProfReader(std::unique_ptr DataBuffer) : DataBuffer(std::move(DataBuffer)) {} Index: lib/ProfileData/InstrProf.cpp =================================================================== --- lib/ProfileData/InstrProf.cpp +++ lib/ProfileData/InstrProf.cpp @@ -360,6 +360,21 @@ return Error::success(); } +uint64_t InstrProfSymtab::getFunctionHashFromAddress(uint64_t Address) { + finalizeSymtab(); + auto Result = + std::lower_bound(AddrToMD5Map.begin(), AddrToMD5Map.end(), Address, + [](const std::pair &LHS, + uint64_t RHS) { return LHS.first < RHS; }); + // Raw function pointer collected by value profiler may be from + // external functions that are not instrumented. They won't have + // mapping data to be used by the deserializer. Force the value to + // be 0 in this case. + if (Result != AddrToMD5Map.end() && Result->first == Address) + return (uint64_t)Result->second; + return 0; +} + Error collectPGOFuncNameStrings(ArrayRef NameStrs, bool doCompression, std::string &Result) { assert(!NameStrs.empty() && "No name data to emit"); @@ -560,32 +575,19 @@ // Map indirect call target name hash to name string. uint64_t InstrProfRecord::remapValue(uint64_t Value, uint32_t ValueKind, - ValueMapType *ValueMap) { - if (!ValueMap) + InstrProfSymtab *SymTab) { + if (!SymTab) return Value; - switch (ValueKind) { - case IPVK_IndirectCallTarget: { - auto Result = - std::lower_bound(ValueMap->begin(), ValueMap->end(), Value, - [](const std::pair &LHS, - uint64_t RHS) { return LHS.first < RHS; }); - // Raw function pointer collected by value profiler may be from - // external functions that are not instrumented. They won't have - // mapping data to be used by the deserializer. Force the value to - // be 0 in this case. - if (Result != ValueMap->end() && Result->first == Value) - Value = (uint64_t)Result->second; - else - Value = 0; - break; - } - } + + if (ValueKind == IPVK_IndirectCallTarget) + return SymTab->getFunctionHashFromAddress(Value); + return Value; } void InstrProfRecord::addValueData(uint32_t ValueKind, uint32_t Site, InstrProfValueData *VData, uint32_t N, - ValueMapType *ValueMap) { + InstrProfSymtab *ValueMap) { for (uint32_t I = 0; I < N; I++) { VData[I].Value = remapValue(VData[I].Value, ValueKind, ValueMap); } @@ -665,13 +667,13 @@ } void ValueProfRecord::deserializeTo(InstrProfRecord &Record, - InstrProfRecord::ValueMapType *VMap) { + InstrProfSymtab *SymTab) { Record.reserveSites(Kind, NumValueSites); InstrProfValueData *ValueData = getValueProfRecordValueData(this); for (uint64_t VSite = 0; VSite < NumValueSites; ++VSite) { uint8_t ValueDataCount = this->SiteCountArray[VSite]; - Record.addValueData(Kind, VSite, ValueData, ValueDataCount, VMap); + Record.addValueData(Kind, VSite, ValueData, ValueDataCount, SymTab); ValueData += ValueDataCount; } } @@ -705,13 +707,13 @@ } void ValueProfData::deserializeTo(InstrProfRecord &Record, - InstrProfRecord::ValueMapType *VMap) { + InstrProfSymtab *SymTab) { if (NumValueKinds == 0) return; ValueProfRecord *VR = getFirstValueProfRecord(this); for (uint32_t K = 0; K < NumValueKinds; K++) { - VR->deserializeTo(Record, VMap); + VR->deserializeTo(Record, SymTab); VR = getValueProfRecordNext(VR); } } Index: lib/ProfileData/InstrProfReader.cpp =================================================================== --- lib/ProfileData/InstrProfReader.cpp +++ lib/ProfileData/InstrProfReader.cpp @@ -438,7 +438,7 @@ // Note that besides deserialization, this also performs the conversion for // indirect call targets. The function pointers from the raw profile are // remapped into function name hashes. - VDataPtrOrErr.get()->deserializeTo(Record, &Symtab->getAddrHashMap()); + VDataPtrOrErr.get()->deserializeTo(Record, Symtab.get()); CurValueDataSize = VDataPtrOrErr.get()->getSize(); return success(); } Index: test/tools/llvm-profdata/invalid-profdata.test =================================================================== --- test/tools/llvm-profdata/invalid-profdata.test +++ test/tools/llvm-profdata/invalid-profdata.test @@ -20,7 +20,7 @@ RUN: echo "1" >> %t.input RUN: echo ":10" >> %t.input -RUN: not llvm-profdata merge %t.input -text -output=/dev/null 2>&1 | FileCheck %s --check-prefix=BROKEN +RUN: not llvm-profdata merge %t.input -text -output=%t.out.broken 2>&1 | FileCheck %s --check-prefix=BROKEN BROKEN: Malformed instrumentation profile data RUN: echo ":ir" > %t.input Index: unittests/ProfileData/InstrProfTest.cpp =================================================================== --- unittests/ProfileData/InstrProfTest.cpp +++ unittests/ProfileData/InstrProfTest.cpp @@ -770,7 +770,7 @@ Symtab.mapAddress(uint64_t(callee4), 0x4000ULL); // Missing mapping for callee5 - VPData->deserializeTo(Record, &Symtab.getAddrHashMap()); + VPData->deserializeTo(Record, &Symtab); // Now read data from Record and sanity check the data ASSERT_EQ(5U, Record.getNumValueSites(IPVK_IndirectCallTarget));